【问题标题】:All closest pairs of points with minimum distance in a plane平面中所有距离最小的最近点对
【发布时间】:2019-11-23 14:01:44
【问题描述】:

我必须从给定集合中找到平面中所有最近的点对。

我已经成功实现了一个类似于这个伪代码函数的朴素算法O(n²),其中set 是输入上所有点的列表,count 是输入上所有点的计数,它返回dist是找到的最小距离,result 是具有该距离的所有点对的列表。

function naive(Points[] set, int count)
    result = []
    distance = INF

    for i=0 to count-1:
        for j=i+1 to count:
           newDistance = distance(set[i], set[j])
           if newDistance < distance:
              result = []
              result.append({set[i], set[j]})
           else if newDistance == distance:
              result.append({set[i], set[j]})

   return (dist, result)

此解决方案效果很好,但由于O(n²) 的复杂性很高,因此对于较大的输入非常慢。我想找到一个更快、更优化的解决方案,所以我使用基于this article 的递归分治算法实现了O(n logn) 解决方案,该算法适用于大多数输入,但由于这种方法不会遍历所有它在像这样的输入上失败的点(对的顺序和对内的点顺序无关紧要):

Input:
{A[0,0], B[1,0], C[1,1] D[0,1]}

Current (wrong) output:
{A[0,0], D[0,1]}, {B[1,0], C[1,1]}

Desired output:
{A[0,0], B[0,1]}, {A[0,0], D[0,1]}, {C[1,1], B[1,0]}, {C[1,1], D[1,0]}

而且由于它是递归的,因此对于较大的输入,堆栈很容易溢出。有什么更好的方法来解决这个问题?

谢谢

【问题讨论】:

标签: algorithm recursion optimization


【解决方案1】:

但您无需将所有内容与其他所有内容进行比较。对于任何给定的点对,假设它们位于矩形的 [与坐标轴对齐的矩形] 对角线上,长度为 d

  • 如果斜率为正:
    • 位于x = d 线左侧的任何其他点将更远,不应考虑。
    • 位于y = d 线下方的任何其他点将更远且不应考虑。
  • 如果斜率为负:
    • 位于线 x = d 右侧的任何其他点将更远,不应考虑。
    • 位于y = d 线下方的任何其他点将更远且不应考虑。

可以想象类似的约束在每种情况下都会给你一个边界框,它应该可以消除你内部循环中需要考虑的大部分点,除非你有一个特别密集的星座。

您在这里肯定需要相当多的动态编程才能为大型集合提供合理的运行时间。

【讨论】:

    【解决方案2】:

    最佳解决方案可能因分数的分配方式而异。一种方法是将正方形划分为许多较小的子正方形,选择这些子正方形以使每个子正方形平均具有大约 1 个点。接下来,将点与相应的子正方形相关联。最后,对于任何给定点,您只需要考虑最近的子方格即可找到最近的邻居(通过检查所有可能包含更近点的子方格来确认 Nearesr 状态)。

    【讨论】:

      【解决方案3】:

      关于第一个问题。我可能记错了,但我可以给你一些提示。

      假设您有 1000 分。您将它们按 250 个点分成 4 组,然后从所有组对中制作 500 个元素集。共 6 个。在这种情况下,任何一对点都将被一半(一对组)覆盖。并且不要忘记保留所有最小值,而不是在每次递归迭代中保留一个。

      另外,因为每次划分集合都要进行分组,这里增加了复杂度,所以你可能会考虑“慢”O(n²)小集合的算法,所以实际的解决方案将是O(n log n)的组合和O(n²)

      对于第二个问题,我只能建议避免递归的一般方法。如果您有足够的内存,请使用动态编程,即将所有以前的结果保存在内存中并遍历,直到用所有可能的参数填充数组。因此,无需进行递归调用,您只需从数组中获取值。当然,您必须重新开始,直到数组中没有空值。实现方式因任务而异,因此您必须考虑如何实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-05
        • 2014-08-13
        • 1970-01-01
        相关资源
        最近更新 更多