从另一组中找到一组中的最远点

时间:2009-02-26 20:31:38

标签: algorithm 3d geometry

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

考虑两组点(在N空间中.3空间用于RGB颜色空间的示例情况,而 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且R%4 = 0且G%4 = 0和B%4 = 0)到另一组中的每个点(colorTable)。为了这个问题,忽略第一个集合以编程方式进行详细说明,而不是像第二个集合那样作为存储列表进行迭代。

6 个答案:

答案 0 :(得分:10)

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

要有效地执行此操作,您需要nearest neighbor算法。就个人而言,我会实现一个kd-tree,因为我在算法类中已经完成了它并且它非常简单。另一个可行的替代方案是R-tree

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

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

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

然后,一旦完成,只需要求堆最大。

此运行时间分解如下:

N =较小组的尺寸
M =较大集合的大小

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

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

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

*免责声明:这一切都假设您不会使用极高数量的维度,并且您的元素主要是随机分布。

答案 1 :(得分:0)

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

完成后,你走过另一组中的所有点,并使用树在第一组中找到最近的邻居,随时跟踪最大值。

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

答案 2 :(得分:0)

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

例如,如果你在2空间工作,将你的飞机划分为5 x 5网格,给出25个方格,有25组点。

在3个空间中,将立方体划分为5 x 5 x 5网格,给出125个立方体,每个立方体都有一组点。

然后,为了测试点n,找到包含n的方形/立方体/组以及到这些点的测试距离。如果点n更接近边缘而不是组中最近的邻居,则只需要测试相邻组中的点。

答案 3 :(得分:0)

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

要找到距离每个最近邻居的距离,只要维度数量合理,点数不多,你就可以使用kd-tree,并且你会做很多查询 - 否则它会太贵了,不值得建树。

答案 4 :(得分:0)

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

答案 5 :(得分:-1)

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

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

使用这样的结构

Struct Item {
    int value
    int setid
}

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

返回最大距离。