找到距离最远的点的算法 - 优于O(n ^ 2)?

时间:2011-06-29 16:52:08

标签: algorithm math language-agnostic geometry

在我的节目中,我有一套积分。为了重新缩放,我正在搜索最远的两个节点,然后计算一个乘以所有坐标的因子,以便最大距离等于我定义的某个预定义的距离。

然而,我用来找到距离最远的两个点的算法对于大的点集是有问题的,因为它是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

有更快的东西吗?

8 个答案:

答案 0 :(得分:18)

如果您只需要比例而不是确切的点,您可以在O(n)时间内执行此操作并获得一些误差。想想制作边界框的简单案例。计算所有点的最小x值,最大x,最小y和最大y。这四个数字为您提供了围绕您的点的最大边界框,最大误差为1 - (1 / sqrt(2))约30%。您可以通过在方块中添加更多边来减少此操作。想想八角形的情况。要计算其他边的最小值和最大值,必须旋转坐标系。

错误与运行时间分解如此。

形状 - 运行时间 - 最大错误

  • square - 2N - 30%
  • 八角形 - 4N - 16%
  • 16面 - 8N - 4%
  • 32边 - 16N - 1%

这是我想出的最大误差的等式。

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点集的“直径”,这是计算几何中众所周知的问题。基本上有两个步骤:

  1. 找到点的凸包。 Algorithms exist是O(N ln N),最坏的情况。实际上,QuickHull通常是一个快速的选择,尽管可能是O(N ^ 2)最坏的情况。从命令行调用QHull implementation很方便。 CGAL库提供C++ implementation

  2. 凸包上的对映对是最远点的候选对象。可以在O(N)时间内使用类似Rotating calipers的算法搜索对映点。

  3. 问题可以归结为“所有最远对”问题:对于每个i,找到最远点j ---我们是现在寻求N对积分。该解决方案再次使用凸包,但现在第二部分可以使用matrix searching算法完成。

答案 3 :(得分:4)

不是真的 - 一种常见的方法是将点组合成簇,然后存储簇之间的距离。

如果您已经确定澳大利亚距离更远,那么您不需要检查纽约的某个房子离巴黎是否最远

答案 4 :(得分:3)

AB的距离与从BA的距离相同。您可以轻松修改算法以通过这种方式消除一半的计算。它仍然是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)。