我有两组2D点,通过平面中的一条线相互分开。我想有效地找到一对点,由每组中的一个点组成,它们之间的距离最小。 Radu Litiu有一篇非常方便的论文,两个分开的点集最近对,但它使用L1(曼哈顿)距离度量而不是欧几里德距离。
有没有人知道类似的算法与欧几里德距离有效吗?
我可以看到标准鸿沟的扩展&征服最近对算法 - 将两组划分为垂直于原始分裂线的中线,在两侧递归,然后寻找由中位数每侧的一个点组成的更接近的对。如果距离递归步骤的最小距离是d,那么中位数一侧的点的伴随必须位于维度为2d * d的方框内。但与原始算法不同,我看不到任何限制该框内点数的方法,因此算法整体上变为O(m * n)。
有什么想法吗?
答案 0 :(得分:2)
对于一组中的每个点,在另一组中找到最近点。在这样做时,只保留一对点之间的距离最小。这减少了给另一个问题:"Algorithm to find for all points in set A the nearest neighbor in set B",可以使用扫描线算法在(1)一组点和(2)Voronoi图解决其他集合。
算法复杂度为O((M + N)log M)。并且该算法不使用两组点彼此分开的事实。
答案 1 :(得分:2)
Evgeny's answer有效,但没有库支持需要付出很多努力:计算完整的Voronoi图和额外的扫描线算法。按顺序枚举Voronoi单元格与分离线相交的点的两组点更容易,然后通过线性时间合并步骤测试其单元格相交的所有点对。
要计算Voronoi图的所需片段,假设x轴是分离线。通过x坐标对集合中的点进行排序,丢弃具有大于等于x的其他点的y的点。开始按x坐标顺序扫描点,将它们推入堆栈。在推动之间,如果堆栈具有至少三个点,比如p,q,r,最近推动r,则测试在二等分qr之后,二等分pq的线是否与分离线相交。如果是这样,丢弃q,并用新的前三个重复测试。原始ASCII艺术:
Case 1: retain q
------1-2-------------- separating line
/ |
p / |
\ |
q-------r
Case 2: discard q
--2---1---------------- separating line
\ /
p X r
\ /
q
答案 2 :(得分:0)
解决此问题的典型方法是扫描线算法。假设您有一个包含所有点的坐标系以及将点与不同集分开的线。现在想象一条垂直于分离线的线,从一个点到另一个点按升序跳跃。为方便起见,您可以旋转和平移点集和分离线,使分离线等于x轴。扫描线现在与y轴平行。
使用扫描线从一个点跳到另一个点,跟踪不同组中两点的最短距离。如果前几个点都来自同一个集合,那么很容易找到一个公式,告诉你哪一个你必须要记住,直到你从另一个集合中找到第一个点。
假设您总共有N个积分。您必须对O中的所有点进行排序(N * log(N))。扫描线算法本身将在O(N)中运行。
答案 3 :(得分:0)
那么这个:
确定任何一方在哪一方:
找到任何(Pi,Pj)的最小距离,其中(Pi)!= side(pj)
您可以通过“排序”来自AB的“距离”点Pi,Pj进一步优化搜索
答案 4 :(得分:0)
(我不确定这是否与大卫的想法有任何相似之处......我现在只是在登录发表我的想法后才看到它。)为了论证,让我们说我们改变了一切所以划分line是x轴,并按x坐标对我们的点进行排序。假设N不是太大,如果我们沿着x轴扫描(也就是说,遍历我们的a和b的排序列表),我们可以记录总体最小值和两个传递点列表。扫描中的当前点针对来自另一个列表的每个传递点进行测试,而从列表中的点到(我们的扫描的x坐标,0)的距离大于或等于整体最小值。在下面的示例中,当到达b2
时,我们可以停止在a2
进行测试。
scan ->
Y
| a2
|
| a1 a3
X--------------------------
| b1 b3
| b2