在我的节目中,我有一套积分。为了重新缩放,我正在搜索最远的两个节点,然后计算一个乘以所有坐标的因子,以便最大距离等于我定义的某个预定义的距离。
然而,我用来找到距离最远的两个点的算法对于大的点集是有问题的,因为它是O(n^2)
;伪代码(已经计算的距离被跳过):
for each point in points:
for each other point in points:
if distance between point and other point > max
max = distance between point and other point
有更快的东西吗?
答案 0 :(得分:18)
如果您只需要比例而不是确切的点,您可以在O(n)时间内执行此操作并获得一些误差。想想制作边界框的简单案例。计算所有点的最小x值,最大x,最小y和最大y。这四个数字为您提供了围绕您的点的最大边界框,最大误差为1 - (1 / sqrt(2))约30%。您可以通过在方块中添加更多边来减少此操作。想想八角形的情况。要计算其他边的最小值和最大值,必须旋转坐标系。
错误与运行时间分解如此。
形状 - 运行时间 - 最大错误
这是我想出的最大误差的等式。
angle = 180 / sides
max_error = (1 / cos angle) - cos angle
如果我应该添加一个解释这一点的图表,请告诉我。
答案 1 :(得分:16)
以下内容可能有助于将平均情况线性时间算法(针对有限集的直径)放在更清晰的光线中,以及对比多维和平面几何问题。
1983年,米吉多为the smallest enclosing circle(或更高维度的球体)提供了确定性线性时间算法。
在一般位置,封闭圆在其边界上将具有两个或三个点,因此一旦知道了边界圆,就可以在恒定时间内“平均”地找到最远的两个点。在更高的维度中,球体边界上所需的一般位置的点数增加(维度D的D + 1点),并且实际上计算单对点之间的距离的成本随着维度线性上升。
位于边界圆或球面上的点子集也可以在线性时间内找到。在理论上最坏的情况下,所有点都位于边界圆或球面上,但这至少比在凸包上具有所有点更严格。如果球体上的点被独立地扰动,例如沿着径向线,则以概率1确保一般位置,并且可以从修改的封闭球体上的仅D + 1点找到近似直径。这种随机近似具有二维的维数依赖性,但只有点数的线性复杂度。
如果位于边界圆上的点被“排序”(当然是循环的),找到最远的对可以在线性时间内完成,依赖于圆的“单峰性”(意味着距离固定的距离)点单调上升直到对映然后下降)to amortize the cost of computing distances。不幸的是,排序将引入具有O(n log n)时间复杂度的步骤,并且这被证明是对于平面情况中的精确确定性方法的最坏情况最优。
2001年,拉莫斯成功地展示了an O(n log n) deterministic algorithm for three-dimensional sets,但该技术非常复杂,实施可能是impractical or slower than brute force all-pairs search up to very large datasets。
对于更高维度,许多作者已考虑randomized或近似算法。有关近似方法,请参阅Piotr Indyk's thesis (2000),其中只有多项因素依赖于各种邻近问题的维度。
答案 2 :(得分:13)
如this answer中所述,您正在寻找N点集的“直径”,这是计算几何中众所周知的问题。基本上有两个步骤:
找到点的凸包。 Algorithms exist是O(N ln N),最坏的情况。实际上,QuickHull通常是一个快速的选择,尽管可能是O(N ^ 2)最坏的情况。从命令行调用QHull implementation很方便。 CGAL库提供C++ implementation
凸包上的对映对是最远点的候选对象。可以在O(N)时间内使用类似Rotating calipers的算法搜索对映点。
问题可以归结为“所有最远对”问题:对于每个点i
,找到最远点j
---我们是现在寻求N对积分。该解决方案再次使用凸包,但现在第二部分可以使用matrix searching算法完成。
答案 3 :(得分:4)
不是真的 - 一种常见的方法是将点组合成簇,然后存储簇之间的距离。
如果您已经确定澳大利亚距离更远,那么您不需要检查纽约的某个房子离巴黎是否最远
答案 4 :(得分:3)
从A
到B
的距离与从B
到A
的距离相同。您可以轻松修改算法以通过这种方式消除一半的计算。它仍然是O(n^2)
,但速度是原来的两倍。
即,不是计算距离矩阵P x P
的所有非对角线元素:
P = {A, B, C, D, ...}
+ A + B + C + D + ...
A | | * | * | * | ...
B | * | | * | * | ...
C | * | * | | * | ...
D | * | * | * | | ...
| | | | |
你可以计算上三角形:
+ A + B + C + D + ...
A | | * | * | * | ...
B | | | * | * | ...
C | | | | * | ...
D | | | | | ...
| | | | |
或下三角:
+ A + B + C + D + ...
A | | | | | ...
B | * | | | | ...
C | * | * | | | ...
D | * | * | * | | ...
| | | | |
答案 5 :(得分:3)
请参阅John Feminella's excellent answer此类似问题。对于普通情况,你应该得到O(n log n)。
答案 6 :(得分:1)
我不确定是否将这些点放入spatial index并查询它会导致O(n log n)算法。
答案 7 :(得分:1)
如果经常执行此查询但点数变化不大,则可以执行可以加快速度的预先计算。
如果新点更远,每个点可以存储距离它最远的点并重新检查每个点的加法。
当您查询时,只需通过所有点并查看其缓存点。
对于新的点输入,最终得到O(n),对于最远的查询,最终得到O(n)。