973. 最接近原点的 K 个点 #
链接 #
题目 #
给定一个数组 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]] 也会被接受。)
提示:
1 <= k <= points.length <= 104
-104 < xi, yi < 104
解答 #
class Solution:
def kClosest(self, points: List[List[int]], k: int) -> List[List[int]]:
import heapq
h_points = list(map(lambda p: (p[0]*p[0] + p[1]*p[1], p), points))
heapq.heapify(h_points)
results = []
while k > 0:
results.append(heapq.heappop(h_points)[1])
k -= 1
return results
#include <vector>
#include <queue>
#include <utility> // for std::pair
class Solution {
public:
std::vector<std::vector<int>> kClosest(std::vector<std::vector<int>>& points, int k) {
// 定义一个优先队列,队列中元素按照距离平方从小到大排序
auto comp = [](const std::pair<int, int>& a, const std::pair<int, int>& b) {
return a.first > b.first; // 注意这里是大于号,以实现最小堆
};
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, decltype(comp)> pq(comp);
// 遍历所有点,计算距离平方,并加入优先队列
for (int i = 0; i < points.size(); ++i) {
int dist = points[i][0] * points[i][0] + points[i][1] * points[i][1];
pq.emplace(dist, i); // emplace插入元素,第一个参数是距离平方,第二个参数是点的索引
if (pq.size() > k) {
pq.pop(); // 如果队列大小超过k,弹出距离最远的点
}
}
// 从优先队列中取出前k个最接近原点的点
std::vector<std::vector<int>> result;
while (!pq.empty()) {
result.push_back(points[pq.top().second]);
pq.pop();
}
// 因为优先队列是按照最小堆来组织的,所以我们需要反转结果数组
std::reverse(result.begin(), result.end());
return result;
}
};
这道题也可以用快速选择算法
#include <vector>
#include <cstdlib> // for rand()
class Solution {
public:
std::vector<std::vector<int>> kClosest(std::vector<std::vector<int>>& points, int k) {
quickSelect(points, 0, points.size() - 1, k);
// 返回前k个最接近原点的点
return std::vector<std::vector<int>>(points.begin(), points.begin() + k);
}
private:
// 辅助函数,计算点到原点的距离平方
int dist(const std::vector<int>& point) {
return point[0] * point[0] + point[1] * point[1];
}
// 快速选择算法的实现
void quickSelect(std::vector<std::vector<int>>& points, int left, int right, int k) {
if (left == right) return;
int pivotIndex = rand() % (right - left + 1) + left; // 随机选择一个基准点
int pivotDist = dist(points[pivotIndex]);
// 将基准点交换到数组的最后
std::swap(points[pivotIndex], points[right]);
int i = left;
for (int j = left; j < right; ++j) {
if (dist(points[j]) < pivotDist) {
std::swap(points[i], points[j]);
i++;
}
}
// 将基准点交换回它的最终位置
std::swap(points[i], points[right]);
// 根据基准点的位置与k的比较结果,递归地在左子数组或右子数组中查找
if (k < i) {
quickSelect(points, left, i - 1, k);
} else if (k > i) {
quickSelect(points, i + 1, right, k);
}
}
};