题目
我们有一个由平面上的点组成的列表 points。需要从中找出 K 个距离原点 (0, 0) 最近的点。
(这里,平面上两点之间的距离是欧几里德距离。)
你可以按任何顺序返回答案。除了点坐标的顺序之外,答案确保是唯一的。
示例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]]。
题解
全排序
- 将计算好的欧几里德距离放在数组第3位
- 根据数组第3位数据大小对数组全排序
- 返回前k的数据
代码
var kClosest = function(points, k) {
const list = [];
points.forEach(v=>{
const n = v[0] * v[0] + v[1] * v[1]
v[2] = n;
})
points.sort((a,b)=>a[2] - b[2]);
const result = [];
for(let i = 0 ; i < k ; i++){
result.push([points[i][0],points[i][1]])
}
return result
};
上述代码可以AC,但是吧,修改了原数组,还多执行了一个循环;怪怪的,仔细看,我都怀疑我智商,为啥非要将欧几里德距离计算出来放在数组中,在排序的时候计算一下不行吗?所以就有了下面代码;
我是菜鸡。
var kClosest = function(points, k) {
points.sort((a,b)=>(a[0] * a[0] + a[1] * a[1]) - (b[0] * b[0] + b[1] * b[1]));
const result = [];
for(let i = 0 ; i < k ; i++){
result.push([points[i][0],points[i][1]])
}
return result
};
堆
- 将计算好的欧几里德距离放在数组第3位
- 利用堆排序将数组放在大根堆中,大根堆超出k个删除堆顶元素
- 返回前k的数据
代码
var kClosest = function (points, k) {
const list = []
points.forEach((v) => {
const n = v[0] * v[0] + v[1] * v[1]
v[2] = n
})
class Heap {
constructor(compare) {
this.list = [0]
this.compare =
typeof compare === 'function' ? compare : this.defaultCompare
}
defaultCompare(a, b) {
return a > b
}
swap(x, y) {
const t = this.list[x]
this.list[x] = this.list[y]
this.list[y] = t
}
isEmpty() {
return this.list.length === 1
}
getSize() {
return this.list.length - 1
}
top() {
return this.list[1]
}
left(x) {
return 2 * x
}
right(x) {
return 2 * x + 1
}
parent(x) {
return Math.floor(x / 2)
}
push(val) {
// 新增数据,向堆尾添加
this.list.push(val)
this.up(this.list.length - 1)
}
// 上浮
up(k) {
const { list, parent, compare } = this
while (k > 1 && compare(list[k], list[parent(k)])) {
this.swap(parent(k), k)
k = parent(k)
}
}
pop() {
const { list } = this
if (list.length === 0) return null
this.swap(1, list.length - 1)
const top = list.pop()
this.down(1)
return top
}
down(k) {
const { list, left, right, compare } = this
const size = this.getSize()
while (left(k) <= size) {
let _left = left(k)
if (right(k) <= size && compare(list[right(k)], list[_left])) {
_left = right(k)
}
if (compare(list[k], list[_left])) return
this.swap(k, _left)
k = _left
}
}
}
// 大根堆
const maxHeap = new Heap((a, b) => a[2] > b[2])
points.forEach((v) => {
maxHeap.push(v)
if (maxHeap.getSize() > k) {
maxHeap.pop()
}
})
const result = []
for (let i = 0; i < k; i++) {
const top = maxHeap.top()
maxHeap.pop()
result.push([top[0], top[1]])
}
// console.log(result)
return result
}
var points = [
[3, 3],
[5, -1],
[-2, 4],
],
k = 2
const aa = kClosest(points, k)