【问题标题】:Given two (large) sets of points, how can I efficiently find pairs that are nearest to each other?给定两组(大)点,我如何有效地找到彼此最近的点对?
【发布时间】:2023-03-27 22:41:01
【问题描述】:

我需要解决一个计算问题,该问题归结为在两组之间搜索相互最近的点对。问题是这样的:

给定欧几里得空间中的一组点 A 和一组点 B,找到所有对 (a,b),使得 b 是 B 中离 a 最近的点,a 是 A 中离 b 最近的点。

集合 A 和 B 的大小大致相等,我们称这个大小为 N。对于我的特定问题,N 大约是 250,000。

蛮力解决方案是将每个点与每个其他点进行比较,这具有二次时间复杂度。有没有更有效的算法来做到这一点?

【问题讨论】:

  • 这真的取决于您的数据是如何保存/组织的。我建议查看此 wiki 页面 en.wikipedia.org/wiki/Kd-tree 以获取一些想法。这可以为您提供更有效的搜索,但也可能需要重新格式化您的数据点。
  • 纯技术问题,属于 StackOverflow。
  • 我第二个 @Peter 这是一个特定的问题,因此应该在 SO

标签: algorithm performance computational-geometry


【解决方案1】:

【讨论】:

    【解决方案2】:

    当我必须进行最近邻搜索时,我发现一个非常有用的数据结构是 kd-tree。 Wikipedia 有一个很好的概述,this 是一个很好的深入讨论算法,如果你正在实现自己的算法(尽管一个库很可能已经存在——你没有提到你正在使用哪种语言)。 kd-tree 最重要的一点是它允许在 O(log N) 时间内执行最近邻搜索。

    这样,您可以在 O(N log N) 时间内生成两个列表 - A 的成员及其在 B 中的最近邻居以及 B 的成员及其在 A 中的最近邻居。然后,您可以比较这些列表以查看哪些配对匹配。天真地完成,这是 O(N^2),尽管你可能会想办法更​​快地完成它。

    [编辑] 你让我思考;这是我的第二个想法:

    for(a in A)
        b := nearest(B, a)
        if a = nearest(A, b)
            add (a, b) to results
        end if
    end for
    
    function nearest(X, y)
        return nearest member of set X to point y
    end function
    

    据我估计,这是 O(N log N)。

    【讨论】:

    • 我正在使用 R,而 R 确实有一个包用于通过 kd-trees 查找最近邻。它曾经有一个包用于计算两组点之间的最近邻。 cran.r-project.org/web/packages/RANN/RANN.pdf
    • 使用列表合并可以在 O(N) 时间内完成两个最近邻居列表的组合:只需将每对中元素的顺序交换为(例如)B 的最近邻居,按以下方式排序他们的第一个元素,然后从两个列表的开头向下走,找到两者中都存在的元素并将它们写入输出列表。
    【解决方案3】:

    抱歉,我选择了一个相当老的线程,但我只是想添加一个我在教科书中找到的算法设计课程的解决方案:

    有一种分而治之(想想合并排序)的方法来解决这个问题,应该是O(n logn),我只看到它用于在一组点内找到最短距离,但它应该很容易适应要求每个配对由来自不同集合的点组成。

    1. 根据 X 值对所有点进行排序。
    2. 将整个集合分成两等份。
    3. 在每一半上递归并选择两者的最小距离 (d)
    4. 在左半部分找到最右边的点 (p) 并检查p_xp_x + d 之间所有点的距离,如果这些距离中的任何一个小于d,即@987654327 @ 返回,否则返回 d

    【讨论】:

    • 回到这个答案,如何使它适用于例如3D 案例?
    【解决方案4】:

    旧线程,但我看到有一条最近的评论。

    我相信对于 n 维点集,可以通过找到到集合差异原点的近点来找到两组之间的近点。您可以查找贝尔实验室的 Phillip Wolfe 的论文,他在该论文中介绍了算法。你可以这样想,在集合 A 中取一个随机点,在集合 B 中找到最近的点,然后在集合 B 中找到离该点最近的点,依此类推。 http://link.springer.com/article/10.1007%2FBF01580381

    【讨论】:

      猜你喜欢
      • 2010-12-09
      • 2022-11-01
      • 1970-01-01
      • 2021-02-09
      • 2019-06-06
      • 1970-01-01
      • 1970-01-01
      • 2010-10-03
      • 1970-01-01
      相关资源
      最近更新 更多