【LeetCode】最接近原点的K个点 (优先队列PriorityQueue,快速排序的根据基准数分区思想(双指针法分区))

2023-05-16

【LeetCode】最接近原点的K个点 (优先队列PriorityQueue,快速排序根据基准数分区思想(双指针法分区))

题目:
我们有一个由平面上的点组成的列表 points。需要从中找出 K 个距离原点 (0, 0) 最近的点。(这里,平面上两点之间的距离是欧几里德距离。)
你可以按任何顺序返回答案。除了点坐标的顺序之外,答案确保是唯一的。

示例:

输入:points = [[1,3],[-2,2]], K = 1
输出:[[-2,2]]
解释: (1, 3) 和原点之间的距离为sqrt(10), (-2, 2) 和原点之间的距离为 sqrt(8), 由于 sqrt(8) < sqrt(10),(-2, 2) 离原点更近。 我们只需要距离原点最近的 K = 1 个点,所以答案就是 [[-2,2]]。

此方法是通过两个K长度数组,一个记录相应points二维数组的行索引,另一个记录相应行索引算出来的斜边值。对points进行行遍历,通过数组比较,和数组移动插入,最终实现两个数组中一个记录了前K个离原点最近的点的下标,另一个记录了相应的斜边值。时间复杂度是O(n*n)。此方法是自己想的,虽然可行,但是不高效而且不简洁,唉还是太菜了。

	public int[][] kClosest(int[][] points, int K) {
        int temp[] = new int[K]; //points点的下标
        double tempVal[] = new double[K];  //相应点的欧几里德值
        int ti = 0; 
        for(int i=0;i<points.length;i++) {
            if(ti==0) {
                temp[ti] = i;
                tempVal[ti++] = Math.sqrt(Math.pow(points[i][0],2)+Math.pow(points[i][1],2));
            }else {
                double value = Math.sqrt(Math.pow(points[i][0],2)+Math.pow(points[i][1],2));
                //找到此值应该放在哪个位置
                int index;
                for(index=0;index<ti;index++) {
                    if(value<=tempVal[index]) {
                        break;
                    }
                }
                
                if(index==ti&&ti==K) //大于记录的前K个值
                    continue;
                
                int j;
                if(ti<K)
                    j = ti;
                else
                    j = ti-1;
                for(;j>index;j--) {  //数值的插入
                    tempVal[j] = tempVal[j-1];
                    temp[j] = temp[j-1];
                }
                tempVal[j] = value;
                temp[j] = i;
                
                if(ti<K) {
                    ti++;
                }
            }
            
        }
        
        int newArray[][] = new int[K][2];
        for(int i=0;i<K;i++) {
            newArray[i] = points[temp[i]];
        }
        
        return newArray;
    }

1.快速排序法

直接调用快排函数方法,再加一个比较器(Comparator接口)实现接口匿名内部类。此方法是将所有的值都排序好序了,再来输出前K个。

	public int[][] kClosest(int[][] points, int K) {
        Arrays.sort(points, new Comparator<int[]>() {
            public int compare(int[] point1, int[] point2) {
                return (point1[0] * point1[0] + point1[1] * point1[1]) - (point2[0] * point2[0] + point2[1] * point2[1]);
            }
        });
        return Arrays.copyOfRange(points, 0, K);
    }

2.优先队列

优先队列PriorityQueue是Queue接口的实现,可以对其中元素进行排序,当使用其中的add()或offer()方法给优先队列添加时它每次都会进行自动的排序,优先队列PriorityQueue可加比较器(Comparator)。

 	public int[][] kClosest(int[][] points, int K) {
       PriorityQueue<int[]> pq = new PriorityQueue<int[]>(new Comparator<int[]>() {
            public int compare(int[] array1, int[] array2) {
                return array2[0] - array1[0];
            }
        });
        for (int i = 0; i < K; ++i) {
            pq.offer(new int[]{points[i][0] * points[i][0] + points[i][1] * points[i][1], i});
        }
        int n = points.length;
        for (int i = K; i < n; ++i) {
            int dist = points[i][0] * points[i][0] + points[i][1] * points[i][1];
            if (dist < pq.peek()[0]) {
                pq.poll();
                pq.offer(new int[]{dist, i});
            }
        }
        int[][] ans = new int[K][2];
        for (int i = 0; i < K; ++i) {
            ans[i] = points[pq.poll()[1]];
        }
        return ans;
    }

3.快速选择(快速排序的思想)

因为此题只要求输出前K个最接近原点的坐标,无需从小到大的顺序输出,所以可以用快速排序中的基于基准数分区的思想,不断分区然后取基准数,直到取到的基准数是第K个为止。其中的分区的实现有两种方式:快慢指针与头尾指针(这两种方式者是双指针法)!
A.【快慢指针】实现分区

	Random rand = new Random();

    public int[][] kClosest(int[][] points, int K) {
        int n = points.length;
        random_select(points, 0, n - 1, K);
        return Arrays.copyOfRange(points, 0, K);
    }

    public void random_select(int[][] points, int left, int right, int K) {
        int pivotId = left + rand.nextInt(right - left + 1);
        int pivot = points[pivotId][0] * points[pivotId][0] + points[pivotId][1] * points[pivotId][1];
        swap(points, right, pivotId);
        //【快慢指针法】
        int i = left - 1;
        for (int j = left; j < right; ++j) {
            int dist = points[j][0] * points[j][0] + points[j][1] * points[j][1];
            if (dist <= pivot) {
                ++i;
                swap(points, i, j);
            }
        }
        ++i;
        swap(points, i, right);
        // [left, i-1] 都小于等于 pivot, [i+1, right] 都大于 pivot
        if (K < i - left + 1) {
            random_select(points, left, i - 1, K);
        } else if (K > i - left + 1) {
            random_select(points, i + 1, right, K - (i - left + 1));
        }
    }

    public void swap(int[][] points, int index1, int index2) {
        int[] temp = points[index1];
        points[index1] = points[index2];
        points[index2] = temp;
    }

B.【头尾指针】实现分区

	public  Random rand = new Random();
	
	public  int[][] kClosest(int[][] points, int K){
		Random_select(points,K,0,points.length-1);
		return Arrays.copyOfRange(points,0,K);
	}
	
	//快速排序思想(按基准数分类)
	public  void Random_select(int[][] points,int K,int left,int right) {
		int baseNum = left+rand.nextInt(right-left+1);
		int baseVal = points[baseNum][0]*points[baseNum][0]+points[baseNum][1]*points[baseNum][1];
		swap(points,baseNum,right);
		//定义双指针【头尾指针】
		int i=left;
		int j=right-1;
		//进行对调交换
		int iVal = 0;
		while(i<=j) {
			iVal = points[i][0]*points[i][0]+points[i][1]*points[i][1];
			if(iVal>baseVal) {
				swap(points,i,j--);
				continue;
			}
			i++;
		}
		
		//交换完成,找到基准数的真正位置
		swap(points,i,right);
		//判断是否是等于K
		if(i-left+1>K) {
			Random_select(points,K,left,i-1);
		}else if(i-left+1<K) {
			Random_select(points,K-(i-left+1),i+1,right);
		}
		
		return ;
		
	}
	
	public void swap(int[][] points, int index1, int index2) {
        int[] temp = points[index1];
        points[index1] = points[index2];
        points[index2] = temp;
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【LeetCode】最接近原点的K个点 (优先队列PriorityQueue,快速排序的根据基准数分区思想(双指针法分区)) 的相关文章

  • 练习7-10 查找指定字符 (15分)

    本题要求编写程序 xff0c 从给定字符串中查找某指定的字符 输入格式 xff1a 输入的第一行是一个待查找的字符 第二行是一个以回车结束的非空字符串 xff08 不超过80个字符 xff09 输出格式 xff1a 如果找到 xff0c 在
  • 用cropper.js裁剪图片并上传到服务器,解析base64转存图片到本地

    今天要写上传图片功能 xff0c 研究了一下cropper 将图片上传服务器并保存到本地 html lt html gt lt head gt lt title gt 基于cropper js的图片裁剪 lt title gt lt met
  • 通讯协议详解

    1 xff0c 概念 网络协议指的是计算机网络中互相通信的对等实体之间交换信息时所必须遵守的规则的集合 网络上的计算机之间是如何交换信息的呢 xff1f 就像我们说话用某种语言一样 xff0c 在网络上的各台计算机之间也有一种语言 xff0
  • 自动识别击打控制系统

    目录 摘 要 关键词 一 系统方案 1 1 系统基本方案 1 2 程序算法的具体流程 二 视觉程序识别框架 2 1多线程 2 2 opencv配置文件 2 3 主函数 三 装甲板识别算法 3 1 装甲板识别 3 2 识别函数介绍 四 目标位
  • 基于stm32风力摆控制系统(电赛获得省一)

    目录 需要源文档及程序进入主页 一 系统方案 完整文档以及代码可主页私 1 1 系统基本方案 1 1 1 控制方案设计 1 1 2 机械结构方案设计
  • 基于stm32的所有嵌入式项目代码

    nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 本人本科和硕士阶段的专业都是嵌入式方向 做了许许多多的项目 包括51 stm32 freeRTOS linux操作系统 多进程线程实现功能 包括裸机开发 驱动开
  • 基于图像处理的水果自助售卖系统(自助水果售卖机)

    目录 第一章 nbsp 概述 1 1 发展概要 1 2 国内外研究现状 1 3 研究目的和意义 1 4 方案介绍
  • 基于stm32的无人机控制系统设计

    基于stm32的无人机控制系统设计 整篇文章有两万字左右 字数太多了 实在是懒得全部放在这上面来 太废时间了 需要完整论文可主页联系 第一章 前言 1 1项目背景和意义 1 2国内外发展现状 1 3本文研究的主要内容 第二章 设计方案论证与
  • 基于Robot Studio的工业机器人汽车喷涂仿真设计

    基于Robot Studio的工业机器人汽车喷涂仿真设计 整篇文章字数有一万四左右 图片太多了 实在是懒得全部放在这上面来 太废时间了 获得完整论文关注可查看主页私信我 摘要 关键词 1 绪论 1 1研究背景与意义 1 2国内外研究现状 2
  • 基于单片机的压力流量报警器(附代码+仿真+论文)

    基于单片机的压力流量报警器 附代码 仿真 论文 完整论文 代码 仿真可关注我在主页私我 摘要 关键字 第一章绪论 1 1课题背景及其意义 1 2 国内外的研究状况 1 3本文的主要研究内容及论文结构安排 第二章 方案的设计与论证 2 1控制
  • 基于STM32的微型电子琴设计

    基于STM32的微型电子琴设计 第一章 总体设计 1 1 系统功能 1 2 主要技术性能指标 第二章硬件设计 2 1 整体硬件图 2 2 按键模块 2 3 扬声器模块 2 4 显示模块 2 5 主控模块 第三章 软件设计 3 1 主要工作原
  • 百度2015校园招聘软件开发笔试题及答案

    简单题 xff08 本题共30分 xff09 请简述Tcp ip的3次握手以及4次挥手过程 xff1f 并解释为何关闭连接需要4次挥手 10分 详细答案参见TCP IP协议三次握手与四次握手流程解析 TCP三次握手 四次挥手过程如下 通常情
  • 智能算法实现PID智能车控制系统

    智能算法实现PID智能车控制系统 TOC 智能算法实现PID智能车控制系统 摘要 关键词 第一章绪论 1 1智能车概述 1 2智能PID研究现状 1 3本文工作 第二章 PID控制简介 第三章 内模PID简介 3 1 内模PID控制 第四章
  • esp8266WiFi模块通过MQTT连接华为云

    esp8266WiFi模块通过MQTT连接华为云 总结 xff1a 一 MQTT透传AT固件烧录二 串口调试2 1 设置模块为STA模式2 2 连接WiFi2 3 设置MQTT的登陆用户名与密码2 4 设置MQTT的ClientID2 5
  • tx2性能不够怎么办

    关闭pycharm xff0c 使用终端直接Python3 5 加路径脚本名运行
  • 瑞泰烧录捞取

    关于将pc主机上的镜像文件拷贝到tx2上的方法 一 给Linux主机搭建环境 2 2 解压 Linux Driver Package tar vxjf Tegra lt t arch ver gt Linux R aarch64 tbz2
  • Realsense D435i 在ubuntu上安装SDK与ROS Wrapper 运行ORB-SLAM2、RTAB和VINS-Mono

    前言 等了一个月的realsense d435i终于发货了 xff01 这款D435i xff08 见下图 xff09 在D435的基础上 xff0c 另外搭载了博世的惯性测量单元 xff08 IMU xff09 xff0c 可以作为研究V
  • 如何用Realsense D435i运行VINS-Mono等VIO算法 获取IMU同步数据

    前言 Intel Realsense D435i在D435的基础上硬件融合了IMU xff0c 然而目前网上关于这款摄像头的资料非常少 xff0c 本文主要介绍自己拿着d435i历经曲折最后成功运行VINS Mono的过程 重要 最近官方更
  • VINS-Mono代码解读——启动文件launch与参数配置文件yaml介绍

    前言 一般我们通过以下命令运行VINS Mono跑MH 01数据集 roslaunch vins estimator euroc launch roslaunch vins estimator vins rviz launch rosbag
  • 【VINS论文笔记】A General Optimization-based Framework for Global Pose Estimation with Multiple Sensors

    前言 2019年1月11日 xff0c 港科大VINS Mono的团队发布了VINS的扩展版本 VINS Fusion 其支持多种视觉惯性传感器类型 xff08 单相机 43 IMU xff0c 立体相机 43 IMU xff0c 立体相机

随机推荐