情况:
给出一些带坐标的点(x,y) 范围0&lt; x&lt; 100,000,000和0 < y <100,000,000
我必须找到最小的正方形,其边缘和内部至少包含N个点。
我使用矢量存储坐标并搜索所有正方形,边长minLength到边长maxLength(在相关空间中施加蛮力)
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);
对于我抬起的每个方格,遍历完整的向量,看看它的边缘和内部是否至少有N个点。
这是非常低效的时间。
Q1。在不改变我使用的算法的情况下,我应该使用什么数据结构来提高时间效率? Q2。这个问题的有效算法?
答案 0 :(得分:2)
在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)
回想一下,方形尺寸受到在相对边缘上有点的需要的限制。假设点位于左侧(西侧)和右侧边缘 - 您仍然按x顺序排序点。首先假设左边缘位于最左边的x坐标,然后看看右边缘必须包含N个点。现在将左边缘移动到下一个x坐标并找到一个新的右边缘(从而找到一个新的正方形)。这样做直到正方形的右边缘是最右边的点。
也可能是正方形在y方向受到约束。只需在y方向上对点进行排序并重复,然后选择两个结果之间的最小平方。
由于你在x和y方向的点上线性运行,那部分只是O(N),主导因素是O(N log N)排序。
答案 1 :(得分:1)
请查看http://en.wikipedia.org/wiki/Space_partitioning使用Divide-and-Conquer技术解决此问题的算法。这在多项式时间内绝对可以解决。
另外一种变体算法可以在以下几行。
现在使用动态编程,DP将类似于在2D阵列中找到最大子阵列的问题。这里不是数字之和,而是在它之前保留点数。
2.a基本上类似于此的递归将成立。 [O(n)]
从(0,0)到(x,y)的平方元素数量=(元素数量 从square(0,0到((x-1),y))+(方形0,0 - (x,y-1)中的elems数) - ((0,0)中的元素数 - ((x-1),(y-1)))
对于其邻域以及左侧和上方的所有点,您的重现将不得不改变,而不仅仅是上面的上方和左侧的点。
DP准备就绪后,您可以在O(1)中查询sqare中的点数。 另一个O(n ^ 2)循环从所有可能的组合中找到并找到最小二乘。
您甚至可以先从最小的方块开始贪婪地开始,这样您就可以在找到合适的方块后立即结束搜索。
答案 2 :(得分:1)
rtree允许空间搜索,但没有stl实现,尽管sqlite允许绑定。这可以回答&#34;得到范围内的所有点&#34;,&#34; k最近邻居&#34;
查找具有最密集数据的区域是一个类似于聚类的问题。
迭代点并找到每个点的N个最近的条目。然后生成最小的圆 - 中心将是Max(x) - min(x),Max(y) - min(y)。可以形成包含所有邻居的正方形,并且与圆相比,可以在2r长度和2sqrt(r)长度之间。
O(x)构建结构的时间 O(X N log(X))搜索最小的簇
答案 3 :(得分:1)
注意:第二个问题有很多答案(这可能会带来更大的好处),但我只是指你的第一个问题,即在不改变算法的情况下使用什么数据。
在那里,我认为你使用矢量的选择已经相当不错了,因为通常矢量提供最佳的有效载荷/开销比以及最快的迭代。为了找出具体的瓶颈,请使用分析器,否则您只是在猜测。对于大型向量,有一些事情要避免: