两个列表中元素之间差异的最小差异

时间:2016-12-19 18:47:04

标签: python algorithm np

假设我们有两个长度相同的列表,ls1ls2。例如,我们有

ls1 = [4, 6]
ls2 = [3, 5]

对于ls1中的每个元素,我们必须将其与ls2中的一个元素与一个元素配对,其方式为总计( 绝对 ls1中的元素与ls2中的元素之间的差异很小。一个元素只能匹配一次。在上面的示例中,最佳方法是将4 ls13中的ls2匹配,5中的ls16匹配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

2 个答案:

答案 0 :(得分:4)

可以证明最佳解决方案是对两个列表进行排序,并按排序顺序匹配它们的元素。

证明草图:

  1. 请进行反转,即ab匹配,cda < c, b > d匹配。

  2. 我们可以&#34;交换&#34;这些元素:a->d, c->b。现在a < c, d < b。可以证明此操作永远不会增加答案(通过考虑a, b, c, d的所有可能的相对值)

  3. 因此,总是存在最佳匹配,其中两个列表都被排序。

  4. 这是一个实现此解决方案的高效单行程序:

    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))

我提出了自己的证据:
考虑两个列表xsys由元素组成,按随机顺序排列,x1x2,... xny1,{ {1}},... y2 由于我们试图找出绝对差值的最小和,我们可以使用平方根而不是绝对值,这对找到最小值几乎没有影响。
因此,差异的总和是:

yn

正如我们所看到的,无论我们如何安排两个列表,二次项xn ^ 2和yn ^ 2保持不变。因此,为了获得最小的结果,我们只需要最大化负面项-2xn * yn。

为了做到这一点,我们只需将一个列表中的最大值乘以另一个列表中的最大值,然后对两个列表中的第二大值等进行相同操作(参见{{3}) })。因此,通过对排序列表中的相同索引的列表和乘法元素进行排序,我们可以获得最小的差异总和。