如何快速找到2个不同数组中所有元素对的总和

时间:2017-02-23 15:13:39

标签: python arrays algorithm big-o

所以最近我遇到了这个编程问题,我似乎无法使复杂性降低(我当前的代码在O(n ^ 2)中运行)。

基本上,我有四个不同的整数列表(我使用python btw),正整数和负数,比如列表A,B,C,D。现在,每个列表都有1000个整数,这些整数范围从-25000到25000(含)。现在,假设从每个列表中我们选择一个整数,比如a,b,c,d。我希望以最快的方式找到这些a,b,c,d,使a + b = - (c + d)。

目前,我的方法依赖于遍历a,b和c,d的每个可能组合,然后尝试查找集合中是否存在集合中的元素(a + b) - (c + d )。当然,这是不切实际的,因为它在O(n ^ 2)时间运行,考虑到大的列表大小(1000),更是如此。

因此我想知道是否有人能想到更有效的方法(最好是O(n log n)或更小),如果可能的话用python编码。

道歉,如果它相当混乱。如果您有任何疑问,请通知我,我会尝试提供更多说明。

编辑:

这个问题是一个更大问题的一部分。更大的问题表明,如果我们有4个数字序列,每个数字最多1000个整数,比如A,B,C,D,找到a,b,c,d使得a + b + c + d = 0。

我问了上面的问题,因为a + b + c + d = 0意味着a + b = - (c + d),我认为这将导致解决问题的最快方法。如果有人能想到更快的方式,请与我分享。

提前致谢! :)

2 个答案:

答案 0 :(得分:0)

你的问题不是组合元素对是O(n ^ 2),而是你将天真地结合两个这样的过程最终得到O(n ^ 4)算法的事实。我假设你只需要找到> = 1种方法来加起来0 - 我下面给出的方法很容易扩展到找到所有方式,如果它'需要。

鉴于你有一个相对较窄的接受值范围(-25k到+ 25k,让我们分别调用MIN和MAX),这就是你做的:

创建2个大小为的数组(MAX - MIN + 1)," indicesA"和" indicesB"。这甚至不是0.5 MB的内存,因此在现代系统中无需担心。

现在循环列表A和B的所有元素,就像你正在做的那样。做一些像这样的伪代码(不太熟悉python,所以我不确定它是否有效):

for idxA, valA in enumerate(A):
    for idxB, valB in enumerate(B):
        indicesA[valA + valB - MIN] = idxA + 1
        indicesB[valA + valB - MIN] = idxB + 1

现在只需在循环B和C时使用它作为O(1)查找表:

for valC in C:
    for valD in D:
        neededVal = -(valC + valD) - MIN
        if indicesA[neededVal] > 0:
            print('Found solution: {0} {1} {2} {3}'.format(A[indicesA[neededVal] - 1], 
                 B[indicesB[neededVal] - 1], valC, valD))
  • 使用0s查找表初始化:O(MAX - MIN)(~50k,在这种情况下小于n ^ 2)
  • 通过循环A和B来填充查找表:O(n ^ 2)
  • 循环使用C和D并检查任何解决方案:O(n ^ 2)

总体而言,O(n ^ 2 +(MAX-MIN))=〜O(n ^ 2)具有给定的值。可能不会做得更好。

答案 1 :(得分:0)

您有四个数组,并且想要从每个数组中选择一个数字,以使四个数字的总和为零。此问题的技术名称是4SUM×4。

此问题至少与3SUM×3一样困难,必须从三个数组中选择三个总和为零的数字。只需添加零数组,即可将3SUM×3的实例转换为4SUM×4的实例。因此,任何可以解决您问题的算法都可以用于同时解决3SUM×3问题。

似乎并不确定3SUM×3并不比更著名的3SUM问题容易,但似乎也同样困难。 3SUM×3算法可用于解决3SUM问题或determine with arbitrarily high probability,不存在解决方案。 (将3SUM减小为3SUM×3的唯一问题是3SUM×3允许使用1, 1, -2之类的解决方案,而3SUM则不允许。)3SUM的理论上最好的已知算法只能击败O(n 2 )(log n)的乘方。

鉴于所有这些,您的问题似乎不可能在少于O(n 2 )的时间内渐近地解决。