【问题标题】:Finding the farthest point in one set from another set找到一组中距另一组最远的点
【发布时间】:2010-10-10 04:33:09
【问题描述】:

我的目标是更有效地实现 in this question 提出的算法。

考虑两组点(在 N 空间中。对于 RGB 颜色空间的示例情况是 3 空间,而 1 空间 2 空间的解决方案仅在距离计算上有所不同)。如何找到第一组中距离第二组最近邻最远的点?

在一个 1 空间示例中,给定集合 A:{2,4,6,8} 和 B:{1,3,5},答案将是 8,因为 8 距离 5(它在 B 中的最近邻居)有 3 个单位,而 A 的所有其他成员距离 B 中最近的邻居只有 1 个单位。编辑:1 空间过于简化,因为排序与距离有关以某种方式,它不在更高的维度中。

源问题中的解决方案涉及对一组中的每个点进行蛮力比较(所有 R,G,B 其中 512>=R+G+B>=256 and R%4=0 and G%4= 0 和 B%4=0) 到另一组 (colorTable) 中的每个点。为了这个问题,请忽略第一个集合是通过编程方式详细说明的,而不是像第二个集合那样作为存储列表进行迭代。

【问题讨论】:

    标签: algorithm 3d geometry


    【解决方案1】:

    编辑:我的意思是 nlog(n),其中 n 是两组大小的总和。

    在 1-Space 集合中你可以做这样的事情(伪代码)

    使用这样的结构

    Struct Item {
        int value
        int setid
    }
    

    (1) 最大距离 = 0
    (2) 将所有集合读入Item结构
    (3) 创建一个指向所有项目的指针数组
    (4) 按结构的Item->value字段对指针数组排序
    (5) 从头到尾遍历数组,检查Item->setid是否与之前的Item->setid不同 if(SetID 不同)
    检查此距离是否大于 Max Distance,如果是,请将 MaxDistance 设置为此距离

    返回最大距离。

    【讨论】:

    • 你的回答没有意义。您能否提供 1-space 版本的伪代码?
    • 步骤(4)如何在线性时间内发生?
    • 我为我的错误道歉,1-space 太简单了,排序不是更高维度的可用步骤。
    【解决方案2】:

    首先,您需要在另一个集合中找到每个元素的最近邻。

    要有效地做到这一点,您需要一个nearest neighbor 算法。就我个人而言,我会实现kd-tree,只是因为我过去在我的算法类中已经完成了它,而且它相当简单。另一个可行的替代方案是R-tree

    对最小集合中的每个元素执行一次。 (从小到大添加一个元素,然后运行算法找到它的最近邻。)

    从这里你应该能够得到每个元素的最近邻居列表。

    在寻找最近邻对的同时,将它们保存在一个有序的数据结构中,该结构具有快速加法和快速getMax方法,例如heap,按Euclidean distance排序。

    然后,一旦完成,只需向堆询问最大值。

    运行时间分解如下:

    N = 较小集合的大小
    M = 较大集合的大小

    • N * O(log M + 1) 用于所有 kd-tree 最近邻检查。
    • N * O(1) 用于计算欧几里得距离,然后再将其添加到堆中。
    • N * O(log N) 用于将对添加到堆中。
    • O(1) 得到最终答案:D

    所以最后整个算法是O(N*log M)。

    如果您不关心每对的顺序,您可以通过只保留目前找到的最大值来节省一些时间和空间。

    *免责声明:这一切都假设您不会使用大量的维度,并且您的元素遵循大部分随机分布。

    【讨论】:

      【解决方案3】:

      在我看来,最明显的方法是在一个集合上构建一个树形结构,以便您相对快速地搜索它。 kd-tree 或类似的可能适合此。

      完成此操作后,您遍历另一组中的所有点,并使用树在第一组中找到它们最近的邻居,同时跟踪最大值。

      构建树是 nlog(n),一次搜索是 log(n),所以整个事情应该在 nlog(n) 中运行。

      【讨论】:

      • 如果所有元素都在同一个集合中,则为 true,但有两个集合需要处理。
      • 我想我说的和你的想法差不多,除了跳过堆的东西——除非我误解了这个问题,否则我们只需要找到最大值。
      【解决方案4】:

      为了提高效率,请考虑使用 Pigeonhole 算法 - 按它们在 n 空间中的位置对参考集(您的 colorTable)中的点进行分组。这使您可以有效地找到最近的邻居,而无需迭代所有点。

      例如,如果您在 2 空间中工作,请将您的平面划分为 5 x 5 的网格,给出 25 个正方形,包含 25 组点。

      在 3 个空间中,将您的立方体分成 5 x 5 x 5 的网格,得到 125 个立方体,每个立方体都有一组点。

      然后,为了测试点 n,找到包含 n 的正方形/立方体/组并测试到这些点的距离。如果点 n 比组中最近的邻居更靠近边缘,则只需要测试来自相邻组的点。

      【讨论】:

      • kd-trees 做类似的事情。
      【解决方案5】:

      对于集合 B 中的每个点,求其到集合 A 中最近邻的距离。

      要查找到每个最近邻居的距离,您可以使用kd-tree,只要维度数合理,点数不太多,并且您将进行多次查询 - 否则会太建造这棵树的成本很高。

      【讨论】:

        【解决方案6】:

        也许我误解了这个问题,但是将一个数据集中所有坐标上的符号反转(即将一组坐标乘以-1),然后找到第一个最近的邻居(哪个是最远的邻居)?你可以使用你最喜欢的 knn 算法,k=1。

        【讨论】:

        • 您的方法将找到原始集合中相距最远的对。这不是我想要的。我想要的是找到最近邻居比任何其他点的最近邻居离它们更远的单点。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-25
        • 2021-08-20
        相关资源
        最近更新 更多