我们有一个由平面上的点组成的列表 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]]。
输入:points = [[3,3],[5,-1],[-2,4]], K = 2
输出:[[3,3],[-2,4]]
(答案 [[-2,4],[3,3]] 也会被接受。)
思路:
points中存放的是x、y轴的坐标,距离为z:
求前k个距离最小的点,即前k小的z
遍历求每个位置points中对应的z的大小并且排序,返回前k个元素
都忘记勾股定理还有名字叫"欧几里德定理"...
抛砖引玉
/**
* @param {number[][]} points
* @param {number} K
* @return {number[][]}
*/
var kClosest = function(points, K) {
const newPoints = points.sort((a,b) => Math.sqrt(a[0]*a[0] + a[1]*a[1]) - Math.sqrt(b[0]*b[0] + b[1]*b[1]))
return newPoints.substr(0,K)
};
看了题解才发现本题考查的是排序,上面用api完成就有点流氓了...
找出数组中对前K小的元素排序:
var kClosest = function (points, K) {
if (points.length <= K) return points;
// 快速排序
quickSelect(0, points.length - 1, K);
// 传入左右边界假设分别为最小最大值,从左右边界遍历数组,遇到小于有边界的
function quickSelect(left, right, K) {
let z = sqrt(points[left]), // 校验的点
l = left,
r = right;
while (l <= r) {
// 左侧小于基准
if (sqrt(points[l]) <= z) {
l++;
continue;
}
// 右侧大于基准
if (sqrt(points[r]) > z) {
r--;
continue;
}
// 不满足上面情况,交互指针上位置,继续比较
[points[l], points[r]] = [points[r], points[l]];
l++;
r--;
}
// 上面循环的终止条件是l指针越界、此时r上存在的元素小于基准,则前r小元素包括r指针上的元素
[points[left], points[r]] = [points[r], points[left]];
if (r == K) {
return;
} else if (r < K) {
quickSelect(r + 1, right, K);
} else {
quickSelect(left, r - 1, K);
}
}
// 到[0,0]的距离
function sqrt([x,y]) {
return Math.sqrt(x*x + y*y)
}
return points.slice(0, K);
};