从一个集合中找到离另一个集合最远的点

6

我的目标是更高效地实现这个问题中提出的算法

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

在一个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个回答

10

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

为了高效地完成这个任务,您需要使用最近邻算法。个人建议实现kd树,因为我在算法课程中曾经做过,并且相对来说比较简单。另一个可行的选择是R树

针对较小集合中的每个元素执行此操作一次。(将最小集合中的一个元素添加到较大集合中,并运行算法以查找其最近邻。)

通过这种方式,您应该能够获得每个元素的最近邻列表。

在查找最近邻对时,将它们保存在一个排序数据结构中,该数据结构具有快速添加方法和快速获取最大值方法,例如, 按欧几里得距离排序。

然后,完成后只需向堆请求最大值即可。

此算法的运行时间如下:

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

  • 对于所有kd-tree最近邻居检查,时间复杂度为N * O(log M + 1)。
  • 在将其添加到堆中之前,计算欧几里得距离的时间复杂度为N * O(1)。
  • 将配对项添加到堆中的时间复杂度为N * O(log N)。
  • 获取最终答案的时间复杂度为O(1) :D

因此,整个算法的时间复杂度为O(N*log M)。

如果您不关心每个配对项的顺序,可以通过仅保留迄今为止找到的最大值来节省一些时间和空间。

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


0

我认为最明显的方法是在一个集合上建立一棵树形结构,以便您可以相对快速地搜索它。kd-tree或类似的东西可能比较适合。

做完这个之后,您遍历另一个集合中的所有点,并使用树来查找它们在第一个集合中的最近邻居,同时跟踪最大值。

建立树的时间复杂度为nlog(n),每次搜索的时间复杂度为log(n),因此整个过程应该在nlog(n)内运行。


如果所有元素都在同一集合中,则为真,但有两个集合需要处理。 - Ben S
我觉得我的想法和你的差不多,只是跳过了堆这一环节——除非我误解了问题,我们只需要找到最大值即可。 - Peter

0
为了提高效率,考虑使用鸽巢算法 - 将参考集中的点(即您的colorTable)按它们在n空间中的位置分组。这样可以有效地找到最近的邻居,而无需迭代所有点。
例如,如果您在2空间中工作,请将平面划分为5 x 5网格,共25个正方形,每个正方形有25组点。
在3空间中,将立方体划分为5 x 5 x 5网格,共125个立方体,每个立方体都有一组点。
然后,要测试点n,请找到包含n的正方形/立方体/组,并测试与这些点的距离。如果点n距离组内最近的邻居比较靠近边缘,则只需要测试相邻组的点。

kd树做类似于这样的事情。 - Ben S

0
对于集合B中的每个点,找到它与集合A中最近邻居之间的距离。为了找到每个最近邻居的距离,可以使用kd-tree,只要维度数量合理,点数不太多,并且需要进行多次查询——否则构建树的成本将会太高而不值得。

0
也许我误解了问题,但是难道不是最简单的方法就是在一个数据集中反转所有坐标的符号(即将一个坐标集乘以-1),然后找到第一个最近邻(即最远的邻居)吗?您可以使用您喜欢的knn算法,其中k = 1。

你的方法会找到原始集合中距离最远的一对。但这并不是我想要的。我想要的是找到一个单独的点,其最近邻居比任何其他点的最近邻居与它们之间的距离更远。 - Sparr

-1
编辑:我指的是nlog(n),其中n是两个集合大小之和。

在1-Space集合中,您可以使用以下结构(伪代码):

使用这样的结构

Struct Item {
    int value
    int setid
}

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

返回最大距离。


你的回答没有意义。你能提供一下1空间版本的伪代码吗? - Sparr
步骤(4)如何在线性时间内发生? - Peter
对于我的错误表示歉意,1个空格太简单了,在更高维度上排序不是可用的步骤。 - Sparr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接