情况:
给定一些坐标为(x,y)的点
范围0
我必须找到最小的正方形,该正方形的边缘和内部至少包含N个点。
struct Point
{
int x;
int y;
};
vector<Point> P;
int minLength = sqrt(N) - 1;
int maxLength = 0;
// bigx= largest x coordinate of any point
// bigy= largest y coordinate of any point
// smallx= smallest x coordinate of any point
// smally= smallest y coordinate of any point
(bigx - smallx) < (bigy - smally) ? maxLength = (bigx - smallx) : maxLength = (bigy - smally);
这是相当低效的时间。
Q1。在不更改所使用算法的情况下,应使用哪种数据结构来提高时间效率?
Q2。这个问题的高效算法?
最佳答案
在2个相对的边缘上有点-如果没有,则可以将正方形缩小1并仍然包含相同数量的点。这意味着边缘的可能坐标限于输入点的坐标。但是,输入点可能不在角落。 (对于最小矩形,在所有4条边上都会有点,因为您可以缩小一个尺寸而不会改变另一个尺寸)
接下来要实现的是,每个点将平面划分为4个象限,每个象限包含多个点。 (由于象限有一个像素重叠,所以这些点的总和可能超过点的总数)。假设NW(p)是指向p点西北的点数,即具有x>=px and y>=py
的点数。那么一个正方形中的点数就是NW(bottomleft) + NW(topright) - NW(bottomright) - NW(topleft)
。
计算所有输入点的NW(p)
相当容易。通过x
对它们进行排序,并通过x
对相等的y
进行排序。最西北的点具有NW(p)==0
。如果下一个点在第一个点的东南方,则可以使用NW(p)==1
,否则可以使用NW(p)==0
。在此阶段跟踪SW(p)也是很有用的,因为您正在研究从西到东的点,因此它们没有从北到南排序。计算出NW(p)
后,您可以确定O(1)
中正方形S的点数
回想一下,正方形大小受在相对边缘上具有点的限制。假设这些点位于左侧(西边)和右侧边缘-您仍然可以按x顺序对这些点进行排序。首先假设左边缘在您的最左x坐标处,然后查看右边缘必须包含N个点。现在,将左边缘移动到下一个x坐标,并找到一个新的右边缘(从而找到一个新的正方形)。这样做直到正方形的右边缘是最右边的点。
正方形在y方向上受约束也是可能的。只需沿y方向对点进行排序并重复,然后在两个结果之间选择最小的平方即可。
由于您是线性遍历x和y方向上的点,因此该部分只是O(N),而主导因素是O(N log N)排序。
关于c++ - 高效的数据结构,可进行稀疏数据查找,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24402312/