最近在一次采访中提到了这个问题
public interface PointsOnAPlane {
/**
* Stores a given point in an internal data structure
*/
void addPoint(Point point);
/**
* For given 'center' point returns a subset of 'm' stored points that are
* closer to the center than others.
*
* E.g. Stored: (0, 1) (0, 2) (0, 3) (0, 4) (0, 5)
*
* findNearest(new Point(0, 0), 3) -> (0, 1), (0, 2), (0, 3)
*/
vector<Point> findNearest(vector<Point> points, Point center, int m);
}
这是我使用的方法
1)创建最大堆priority_queue以存储最近的点
priority_queue<Point,vector<Point>,comp> pq;
2)如果优先级队列大小<1,则迭代点向量并推送一个点。米
3)如果size == m,则将队列顶部与当前点进行比较,并在必要时弹出
for(int i=0;i<points.size();i++)
{
if(pq.size() < m)
{
pq.push(points[i]);
}
else
{
if(compareDistance(points[i],pq.top(),center))
{
pq.pop();
pq.push(points[i]);
}
}
}
4)最后将优先级队列的内容放在向量中并返回。
我应该如何编写comp和compareDistance比较器,它允许我最初存储m个点,然后将当前点与顶部的点进行比较?
答案 0 :(得分:0)
我认为您的方法可以更改,以便以不同的方式使用priority_queue
。代码变得有点复杂,因为for循环中有一个if语句,而这个if语句控制何时添加到priority_queue
。为什么不首先将所有点添加到priority_queue
,然后弹出m
点?让priority_queue
完成所有工作。
使用findNearest
实现priority_queue
函数的关键是要意识到比较器可以是捕获中心参数的lambda。所以你可以这样做:
#include <queue>
#include <vector>
using namespace std;
struct Point { int x, y; };
constexpr int distance(const Point& l, const Point& r)
{
return (l.x - r.x)*(l.x - r.x) + (l.y - r.y)*(l.y - r.y);
}
vector<Point> findNearest(const vector<Point>& points, Point center, int m)
{
auto comparator = [center](const Point& l, const Point& r) {
return distance(l, center) > distance(r, center);
};
priority_queue<Point, vector<Point>, decltype(comparator)> pq(comparator);
for (auto&& p : points) {
pq.emplace(p);
}
vector<Point> result;
for (int i = 0; i < m; ++i) {
result.push_back(pq.top());
pq.pop();
}
return result;
}
在采访中,谈论算法中的缺陷也很好。
O(nlogn)
中运行。会有一个聪明的算法可以超过这个运行时间,特别是因为你只需要最接近的m
点。O(n)
更多空间,我们应该能够做得更好。在这个函数中真正发生的是排序,并且可以就地实现排序。Point
结构上的模板。您还可以使用模板在points
函数中使findNearest
容器通用。容器只需支持迭代。