973. K Closest Points to Origin
We have a list of points on the plane. Find the K closest points to the origin (0, 0).
(Here, the distance between two points on a plane is the Euclidean distance.)
You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in.)
Example 1:
Input: points = [[1,3],[-2,2]], K = 1
Output: [[-2,2]]
Explanation:
The distance between (1, 3) and the origin is sqrt(10).
The distance between (-2, 2) and the origin is sqrt(8).
Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.
We only want the closest K = 1 points from the origin, so the answer is just [[-2,2]].
Example 2:
Input: points = [[3,3],[5,-1],[-2,4]], K = 2
Output: [[3,3],[-2,4]]
(The answer [[-2,4],[3,3]] would also be accepted.)
Note:
- 1 <= K <= points.length <= 10000
- -10000 < points[i][0] < 10000
- -10000 < points[i][1] < 10000
方法0:partial_sort
partial: https://www.geeksforgeeks.org/stdpartial_sort-in-cpp/
思路:
用内置的partial_sort,为这道题而生的函数:比如[first, middle)之间有k个数字,将[first, last)范围内的最小的k个数字找到并且ascending order排在前[first, middle)之间,剩下的顺序不变放到后面。One of the variants of std::sort, which is used for sorting not the entire range, but only a sub-part of it. difference with sort: sort(first, middle) only sorts the number in range without minding the rest。
class Solution {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
partial_sort(points.begin(), points.begin() + K, points.end(), [](vector<int>& p, vector<int>& q) {
return p[0] * p[0] + p[1] * p[1] < q[0] * q[0] + q[1] * q[1];
});
return vector<vector<int>>(points.begin(), points.begin() + K);
}
};
方法0: nth_element
class Solution {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
nth_element(points.begin(), points.begin() + K - 1, points.end(), [](vector<int>& p, vector<int>& q) {
return p[0] * p[0] + p[1] * p[1] < q[0] * q[0] + q[1] * q[1];
});
return vector<vector<int>>(points.begin(), points.begin() + K);
}
};
方法1: priority queue
class Solution {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
priority_queue<vector<int>, vector<vector<int>>, compare> pq;
for (vector<int>& point : points) {
pq.push(point);
if (pq.size() > K) {
pq.pop();
}
}
vector<vector<int>> ans;
while (!pq.empty()) {
ans.push_back(pq.top());
pq.pop();
}
return ans;
}
private:
struct compare {
bool operator()(vector<int>& p, vector<int>& q) {
return p[0] * p[0] + p[1] * p[1] < q[0] * q[0] + q[1] * q[1];
}
};
};
class Solution {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
priority_queue<vector<int>, vector<vector<int>>, compare> pq(points.begin(), points.end());
vector<vector<int>> ans;
for (int i = 0; i < K; i++) {
ans.push_back(pq.top());
pq.pop();
}
return ans;
}
private:
struct compare {
bool operator()(vector<int>& p, vector<int>& q) {
return p[0] * p[0] + p[1] * p[1] > q[0] * q[0] + q[1] * q[1];
}
};
};
class Solution {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
multiset<vector<int>, compare> mset;
for (vector<int>& point : points) {
mset.insert(point);
if (mset.size() > K) {
mset.erase(mset.begin());
}
}
vector<vector<int>> ans;
copy_n(mset.begin(), K, back_inserter(ans));
return ans;
}
private:
struct compare {
bool operator()(const vector<int>& p, const vector<int>& q) const {
return p[0] * p[0] + p[1] * p[1] > q[0] * q[0] + q[1] * q[1];
}
};
};
方法2: quick sort
易错题
- 请铭记 else if , else if , else if , else if , else if !!!!!!
class Solution1 {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
K--;
int start = 0, end = points.size() - 1, pos;
while (true){
pos = partition(points, start, end);
if (pos == K) break;
else if (pos < K) {
start = pos + 1;
}
else {
end = pos - 1;
}
}
return vector<vector<int>> (points.begin(), points.begin() + K + 1);
}
int partition(vector<vector<int>> & points, int start, int end){
vector<int> pivot = points[start];
int left = start + 1, right = end;
// 结束时right + 1 = left
// 这个方法的loop invariant是left左边(exclusive)保证>=pivot,返回的应该是left - 1,也就是right
while (left <= right){
if (dis(points[left]) > dis(pivot) && dis(points[right]) <= dis(pivot)){
swap(points[left++], points[right--]);
}
else if (dis(points[left]) <= dis(pivot)) left++;
else if (dis(points[right]) > dis(pivot)) right--;
}
swap(points[start], points[right]);
return right;
}
int dis(const vector<int> &p) {
return p[0] * p[0] + p[1] * p[1];
}
};
方法2: divide and conquer
官方题解:https://leetcode.com/problems/k-closest-points-to-origin/solution/
思路: