题:https://leetcode.com/problems/k-closest-points-to-origin/
题目大意
对于 数组int[][] points,找出 前 K个 离原点最近的 点。
思路大意
大堆求前k个小的点
可以使用 小堆,然后 取 先 k 个数。但这个 O(nlogn)。
使用 大 堆,只用 O(nlogk),堆变小些。
维护一个大堆,当堆容量 小于 k,将 point 直接加入。
若大于 k,将堆顶 与 新point 比较,若新point 较小,将堆顶删除,将新point加入。
class Solution {
public int[][] kClosest(int[][] points, int K) {
PriorityQueue<int []> priorityqueue = new PriorityQueue<>(new Comparator<int[]>(){
public int compare(int[] o1,int[] o2){
return -((o1[0]*o1[0] + o1[1]*o1[1]) - (o2[0]*o2[0] + o2[1]*o2[1]));
}
});
for(int[] point:points){
if(priorityqueue.size()<K)
priorityqueue.add(point);
else{
if(priorityqueue.peek()[0]*priorityqueue.peek()[0]+ priorityqueue.peek()[1]*priorityqueue.peek()[1]>
point[0]*point[0] +point[1]*point[1]){
priorityqueue.poll();
priorityqueue.add(point);
}
}
}
int[][] resPoints = new int[K][2];
for(int i = 0 ; i < resPoints.length ; i++)
resPoints[i] = priorityqueue.poll();
return resPoints;
}
}
使用 快排序的 patition 函数
class Solution {
public int[][] kClosest(int[][] points, int K) {
int l = 0,r = points.length -1;
int k = K-1;
while(l < r){
int p = partition(points,l,r);
if(p < k){
l = p + 1;
}else if(p>k){
r = p -1;
}else
break;
}
int[][] resPoints = new int[K][];
for(int i = 0 ; i < K ; i++)
resPoints[i] = points[i];
return resPoints;
}
void swap(int[][] points ,int a,int b){
int[] tmp = points[a];
points[a] = points[b];
points[b] = tmp;
}
private int partition(int[][] points, int l, int r) {
int il = l ,ir = r;
int pivot = points[l][0]*points[l][0] + points[l][1]*points[l][1];
while (il<ir){
while(il<ir && points[ir][0]*points[ir][0] + points[ir][1]*points[ir][1]>pivot)
ir--;
while(il<ir && points[il][0]*points[il][0] + points[il][1]*points[il][1]<=pivot)
il++;
swap(points,il,ir);
}
swap(points,l,il);
return il;
}
}