标签:queue size 时间复杂度 pop 一个 tps cto public 这一
https://leetcode-cn.com/problems/k-closest-points-to-origin/
?
这个题目比较简单,本质上是一个排序题。先把最简单的快速排序给安排上。
struct Point {
int x;
int y;
int dist;
};
?
struct Compare {
bool operator()(const Point &a, const Point &b) {
return a.dist < b.dist;
}
} cmp;
?
class Solution {
public:
// 时间和空间复杂度:O(NlogN), O(N)
vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
vector<Point> pts;
for (vector<int>& p : points) {
Point pp;
pp.x = p[0];
pp.y = p[1];
pp.dist = pp.x * pp.x + pp.y * pp.y;
pts.emplace_back(pp);
}
?
sort(pts.begin(), pts.end(), cmp);
vector<vector<int>> ans;
for (int i = 0; i < pts.size() && i < K; ++i) {
vector<int> tmp;
tmp.push_back(pts[i].x);
tmp.push_back(pts[i].y);
ans.emplace_back(tmp);
}
return ans;
}
};
?
仔细一想,上述的快速排序代码可能并不是性能最优的。它有以下缺陷:
(1)使用了自定义的数据结构Point
,里面除了平面点的横纵坐标之外还包含了它距离坐标原点欧氏距离的平方值。但这其实是没必要的,因为代码中用vector<int>
存储点坐标,完全可以在这个vector<int>
后面再push_back
一个距离平方值即可。(注意:这违背了不修改函数输入这一原则)
(2)使用了额外的内存空间,可以在原始数据上进行排序(注意:这同样违背了不修改函数输入这一原则)
(3)在K
值远远小于points
中元素个数的情况下,对整个数组进行排序就显得得不偿失了,因为题目可能仅需要求出前几个离坐标原点比较近的点即可。
?
基于以上的分析,我们可以在原始数据上进行堆排序的方法给出另一种性能更好的解决方法。因为直接调用标准库中的优先队列,需要拷贝一份数据。所以空间复杂度还是没变。理论上的时间复杂度也没有变。虽然根据上面的分析下面的优先队列代码会比上面的快排更快一点,但是在力扣上的运行时间竟然比快排更久!看来理论和实际之间的鸿沟还是挺大的。
struct MyCompare {
bool operator()(const vector<int>& a, const vector<int>& b) {
return a[2] > b[2];
}
};
class Solution {
public:
vector<vector<int>> kClosest(vector<vector<int>>& points, int K) {
for (vector<int>& p : points)
p.push_back(p[0] * p[0] + p[1] * p[1]);
priority_queue<vector<int>, vector<vector<int>>, MyCompare> pq(points.begin(), points.end());
vector<vector<int>> ans;
for (int i = 0; i < points.size() && i < K; ++i) {
ans.push_back(pq.top());
pq.pop();
}
// do NOT ignore this step
for (vector<int>& p : ans)
p.pop_back();
return ans;
}
};
标签:queue size 时间复杂度 pop 一个 tps cto public 这一
原文地址:https://www.cnblogs.com/wallace-lai/p/13951260.html