给定两个数组,找到给出两个数组之间最接近距离的排列

时间:2019-01-04 14:59:06

标签: algorithm

假设我有两个长度相同的n数组,分别命名为AB

这两个数组包含实数值。 我们将两个数组之间的距离定义为均方距离。

dist(A,B) = sqrt( sum((A - B)2) )

我想找到A的排列,它给出到B的最小距离。 天真的方法是尝试A的每个排列并记录最小距离。但是,该方法的复杂度为O(n!)。

是否有一种算法的复杂度小于O(n!)?

5 个答案:

答案 0 :(得分:40)

您可以同时对A和B进行排序。在这种情况下,欧几里得距离很小。

如果B必须保持固定,那么您只需要反转排序B所需的排列并将其应用于A的排序版本。

此解决方案确实假定您只想查找一个排列,而不是最简单的排列(因为通过排列进行排序和取消排序将不会非常有效)。


证明: 令S,T为我们的一对数组。 我们可以假设S被排序而不失一般性,因为所有这些 重要的是两组元素之间的映射。

让T为使两个数组之间的距离最小的排列, 并以d为该距离。

假设T不是 排序的。然后存在元素i,js.t。 T_i> T_j

S_i + k1 = S_j
T_i = T_j + k2
where k1,k2 > 0

让x为除i和j之外的所有元素的总距离。

d = x + (S_i - T_i)^2 + ((S_i + k1) - (T_i - k2))^2

如果我们交换T_i和T_j的顺序,那么我们的新距离是:

d' = x + (S_i - (T_i - k2))^2 + ((S_i + k1) - T_i)^2

因此:     d-d'= 2 * k1 * k2,这与我们的假设T等于使距离最小的排列相矛盾,因此必须对排列进行排序。

可以使用多种方法在O(n log n)中对两个数组进行排序。

答案 1 :(得分:34)

您描述的问题等同于Minimum Cost Perfect Matching Problem,可以使用The Hungarian Algorithm有效(准确)解决。在“最小成本完美匹配问题”中,您有一个输入加权二分图,其中两组具有相同的大小n,每个边的成本均为非负数。目标是找到最低成本的完美匹配。

在您的情况下,二部图是biclique。也就是说,一组中的每个顶点都连接到另一组中的每个顶点,并且边(i,j)的代价为(A[i] - B[i])^2(其中i对应于中的索引i数组A和j对应于数组B中的索引j

编辑: 这不是解决该问题的最佳方法。 Ivo Merchiers在效率和简便性方面都提出了a better solution。我之所以不删除答案,是因为我提出的解决方案对于不适用Ivo解决方案的距离度量非常有价值(因为他的方法通过利用欧几里德距离的性质而起作用)。

答案 2 :(得分:10)

您可以对 A B 进行排序,然后匹配相应的元素。

想象一下,有 A Ai Aj 两个元素,分别与 Bi Bj

这些匹配项的错误贡献为:

(Ai-Bi)^ 2 +(Aj-Bj)^ 2

= Ai ^ 2 + Bi ^ 2 + Aj ^ 2 + Bj ^ 2-2(AiBi + AjBj)

交换比赛还是让比赛保持原样更好?

好吧,如果我们交换它们,错误的区别是:

2(AiBi + AjBj)-2(AiBj + AjBi)

〜AiBi-AiBj + AjBj-AjBi

= Ai(Bi-Bj)-Aj(Bi-Bj)

=(Ai-Aj)(Bi-Bj)

因此,如果 A B 的顺序相同,则该乘积为正,并且如果交换它们,该错误将上升。如果它们的顺序不同,则该乘积为负,如果您交换它们,该错误将消失。

如果您反复交换任何乱序的货币对,直到没有这样的货币对,您的错误就会不断减少,最终您将排在第 n 在整个数组中,A n 个最大的 B 相匹配。

仅对它们进行排序和匹配是最佳的,当然,它比匈牙利算法要快。

答案 3 :(得分:6)

根据向量构造二部图。在此图中找到最小的重量完美匹配。

如何构造图形。

  1. AB是图的两个部分。每个节点都有n个节点。
  2. i中的A连接到j中的B,并使其重心为abs(A[i] - B[j])

我相信可以在O(n^2)中完成。

请参见http://www.cse.iitd.ernet.in/~naveen/courses/CSL851/lec4.pdf


如果A中的每个数字在B中只有一个最接近的数字,那么您可以在O(n \log n)中进行此操作。因为您有实数,所以可能是这种情况。

如何?

  1. 排序A O(n \log n)
  2. 二进制搜索B中每个数字的最接近数字。O(n \log n)

如果这些数字来自真实世界,并且甚至具有一些随机性,那么每对数字之间的差异可能是唯一的。您可以通过对输入向量进行实验来验证是否是这种情况。然后问题就容易解决了!

答案 4 :(得分:0)

我在python中需要此功能,因此我将根据Ivo Merchiers的回答在这里分享我的解决方案:

target = [12, 14, 4512, 123, 4412]
source = [12, 14, 120, 4413, 5512]

permutationToSortTarget = [i[0] for i in sorted(enumerate(target), key=lambda x: x[1])] # get permutation that would sort target
permutationNeeded = [i[0] for i in sorted(enumerate(permutationToSortTarget), key=lambda x: x[1])] # get needed permutation

source.sort()
source = [source[i] for i in permutationNeeded] # apply permutation to sorted source