给定一个数组 points ,其中 points[i] = [xi, yi] 表示 X-Y 平面上的一个点,并且是一个整数 k ,返回离原点 (0,0) 最近的 k 个点。
这里,平面上两点之间的距离是 欧几里德距离( √(x1 - x2)2 + (y1 - y2)2 )。
你可以按 任何顺序 返回答案。除了点坐标的顺序之外,答案 确保 是 唯一 的。力扣原文
示例 1:
输入: 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]]。
示例 2:
输入: points = [[3,3],[5,-1],[-2,4]], k = 2
输出: [[3,3],[-2,4]]
(答案 [[-2,4],[3,3]] 也会被接受。)
解题:
class Heap {
constructor(cmp, max) {
const defaultCmp = (a, b) => a > b;
this.list = [];
//默认大顶堆
this.cmp = cmp || defaultCmp;
this.max = max || null;
}
size() {
return this.list.length;
}
top() {
return this.list.length === 0 ? null : this.list[0];
}
push(val) {
this.list.push(val);
if (this.size() > 1) {
this.bubbleUp(this.size() - 1);
}
if (this.max !== null && this.size() > this.max) this.pop();
}
pop() {
if (!this.size()) {
return null;
} else if (this.size() === 1) {
return this.list.pop();
}
const top = this.list[0];
this.list[0] = this.list.pop();
this.bubbleDown(0);
return top;
}
//向上调整
bubbleUp(idx) {
while (idx) {
let parentIdx = (idx - 1) >> 1;
if (this.cmp(this.list[parentIdx], this.list[idx])) {
this.swap(idx, parentIdx);
idx = parentIdx;
} else {
break;
}
}
}
//向下调整
bubbleDown() {
let cur = 0,
leftIdx = 1,
rightIdx = 2,
size = this.size();
while (
(leftIdx < size && this.cmp(this.list[cur], this.list[leftIdx])) ||
(rightIdx < size && this.cmp(this.list[cur], this.list[rightIdx]))
) {
if (
rightIdx < size &&
this.cmp(this.list[leftIdx], this.list[rightIdx])
) {
this.swap(rightIdx, cur);
cur = rightIdx;
} else {
this.swap(leftIdx, cur);
cur = leftIdx;
}
(leftIdx = cur * 2 + 1), (rightIdx = cur * 2 + 2);
}
}
// 交换
swap(i, j) {
[this.list[i], this.list[j]] = [this.list[j], this.list[i]];
}
}
var kClosest = function (points, k) {
const heap=new Heap(
(a,b)=>{
const aVla=a[0]*a[0]+a[1]*a[1]
const bVla=b[0]*b[0]+b[1]*b[1]
return aVla<bVla
},
k
)
points.forEach(element => {
heap.push(element)
});
return heap.list
};