Leetcode 973. K Closest Points to Origin
题目链接: K Closest Points to Origin
难度:Medium
题目大意:
输入一组点的坐标,求离原点最近的K个点,将这K个点以任意顺序输出。经典的前K项问题。参考高赞回答Three solutions to this classical K-th problem.解释得很详细。
思路:
思路1:
将这些点按照到原点的距离来排序,然后输出前K个点。这种方法需要对所有点进行排序,效率较低。
思路2 :
用优先队列来存储离原点最近的K个点。
思路3:
参考快速排序的思想,找到某个元素使它左边有K个数比它小,效率最高。关于快速排序可参看我的文章快速排序个人小结(交换法与挖坑法)。
代码
思路1:
class Solution {
public int[][] kClosest(int[][] points, int K) {
Arrays.sort(points,(o1,o2)->o1[0]*o1[0]+o1[1]*o1[1]-(o2[0]*o2[0]+o2[1]*o2[1]));
return Arrays.copyOfRange(points,0,K);
}
}
思路2:
class Solution {
public int[][] kClosest(int[][] points, int K) {
//用优先队列实现
PriorityQueue<int[]> pq=new PriorityQueue<int[]>((p1,p2)->p2[0]*p2[0]+p2[1]*p2[1]-(p1[0]*p1[0]+p1[1]*p1[1]));//注意优先级与题目要求的相反
for(int[] p:points){
pq.offer(p);
if(pq.size()>K){
pq.poll();
}
}
int[][] res=new int[K][2];
for(int i=K-1;i>=0;i--){
res[i]=pq.poll();
}//pq弹出的元素从后往前放
return res;
}
}
思路3:
class Solution {
public int[][] kClosest(int[][] points, int K) {
//用快速排序实现
int l=0,r=points.length-1;
while(l<=r){
int mid=helper(points,l,r);
if(mid==K){
break;
}
else if(mid<K){
l=mid+1;
}
else{
r=mid-1;
}
}
return Arrays.copyOfRange(points,0,K);
}
private int helper(int[][] A,int l,int r){
int[] x=A[l];
while(l<r){
while(l<r&&compare(A[r],x)>=0){
r--;
}
A[l]=A[r];
while(l<r&&compare(A[l],x)<=0){
l++;
}
A[r]=A[l];
}
A[l]=x;
return l;
}
private int compare(int[] p1,int[] p2){
return p1[0]*p1[0]+p1[1]*p1[1]-(p2[0]*p2[0]+p2[1]*p2[1]);
}
}