假设我们有两个长度相同的列表,ls1
和ls2
。例如,我们有
ls1 = [4, 6]
ls2 = [3, 5]
对于ls1
中的每个元素,我们必须将其与ls2
中的一个元素与一个元素配对,其方式为总计( 绝对 )ls1
中的元素与ls2
中的元素之间的差异很小。一个元素只能匹配一次。在上面的示例中,最佳方法是将4
ls1
与3
中的ls2
匹配,5
中的ls1
与6
匹配1 {}在ls2
中,产生
(4 - 3) + (6 - 5) = 2
我需要一个程序来返回这两个列表中元素之间的最小总差异。列表的长度是任意的,列表中元素的值也是如此(但它们都是正整数)。
我目前知道使用排列来强制解决方案是一种选择,但我需要的是具有最佳时间和空间复杂性的代码。我听说过动态编程的概念,但我不知道如何在我的情况下实现它。提前感谢您的回复。
聚苯乙烯。这是我目前使用排列的强力代码,这在运行时或内存使用方面效率不高:
from itertools import permutations
def minimum_total_difference(ls1, ls2):
length = len(ls1)
possibilities = list(permuations(ls1, length))
out = 10**10
for possibility in possibilities:
out_ = 0
for _ in range(length):
diff = abs(possibility[_] - ls2[_])
out += diff
if out_ < out:
out = out_
return out
答案 0 :(得分:4)
可以证明最佳解决方案是对两个列表进行排序,并按排序顺序匹配它们的元素。
证明草图:
请进行反转,即a
与b
匹配,c
与d
和a < c, b > d
匹配。
我们可以&#34;交换&#34;这些元素:a->d, c->b
。现在a < c, d < b
。可以证明此操作永远不会增加答案(通过考虑a, b, c, d
的所有可能的相对值)
因此,总是存在最佳匹配,其中两个列表都被排序。
这是一个实现此解决方案的高效单行程序:
sum(abs(x - y) for x, y in zip(sorted(xs), sorted(ys)))
答案 1 :(得分:1)
正如@kraskevich指出的那样,答案确实是正确的:
sum(abs(x - y) for x, y in zip(sorted(xs), sorted(ys))
我提出了自己的证据:
考虑两个列表xs
和ys
由元素组成,按随机顺序排列,x1
,x2
,... xn
和y1
,{ {1}},... y2
由于我们试图找出绝对差值的最小和,我们可以使用平方根而不是绝对值,这对找到最小值几乎没有影响。
因此,差异的总和是:
yn
正如我们所看到的,无论我们如何安排两个列表,二次项xn ^ 2和yn ^ 2保持不变。因此,为了获得最小的结果,我们只需要最大化负面项-2xn * yn。
为了做到这一点,我们只需将一个列表中的最大值乘以另一个列表中的最大值,然后对两个列表中的第二大值等进行相同操作(参见{{3}) })。因此,通过对排序列表中的相同索引的列表和乘法元素进行排序,我们可以获得最小的差异总和。