在列表中查找X数字的总和(Python)

时间:2013-10-25 20:54:05

标签: python list sum combinations

我正在尝试在整数列表中找到一个和的组合。

包含总和的数字量受变量限制,例如在列表中 -

[5,2,3,9,1],我想找到10的总和,只有2个数字。

这样程序就会打印出[9,1]。

我是python的新手,有一种简单的方法吗?

谢谢。

7 个答案:

答案 0 :(得分:9)

from itertools import combinations

l = [5,2,3,9,1]

for var in combinations(l, 2):
    if var[0] + var[1] == 10:
        print var[0], var[1]

Combinations从可迭代对象(可以循环的对象)创建tuples的所有可能组合。让我演示一下:

>>> [var for var in combinations([1,2,3,4,5], 2)]
[(1, 2), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]
>>> [var for var in combinations([1,2,3,4,5], 3)]
[(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (1, 4, 5), (2, 3, 4), (2, 3, 5), (2, 4, 5), (3, 4, 5)]

答案 1 :(得分:4)

到目前为止所有的都是O(N ^ 2)或更糟,所以这是一个O(N)解决方案:

l = [7, 9, 6, 4, 2]
s = set([l[0]])
sum = 10
for num in l[1:]:
    diff = sum - num
    if diff in s:
        print num, diff
    else:
        s.add(num)

自OP提出以来,这里有一个更一般的解决方案。我们有:

  • numbers(数字列表)
  • sum(所需金额)
  • n(我们希望与sum求和的元素数量)

最简单的是:

def find_sum_tuple(numbers, sum, n):
  return [tup for tup in itertools.combinations(numbers, n) if sum(tup) == sum]

然而,在渐近性能方面并不是最好的。正如我上面所示,你应该能够通过更加聪明和缓存numbers大小的和来得到渐近O(| n | ^(n - 1 - 1))。

答案 2 :(得分:3)

使用itertools.combinations的蛮力方法:

In [6]: [pair for pair in itertools.combinations(li,2) if sum(pair) == 10]
Out[6]: [(9, 1)]

这为您提供了总和为10的所有对。这在运行时是超指数的,因此如果您的输入很大,您将需要更复杂的算法。

答案 3 :(得分:3)

ls = [5, 2, 3, 9, 1]
sum = 10

while ls:
    num = ls.pop()
    diff = sum - num
    if diff in ls:
        print([num, diff])

答案 4 :(得分:2)

仅用于代码高尔夫目的,这是collections.Counter方法:

import collections
integers_list = [5,2,3,9,1]
integer_counts = collections.Counter(integers_list)
for x in integers_list:
    y = 10 - x
    if (x != y and integer_counts[y]) or (x == y and integer_counts[y] > 1):
        print (x, y) # Or, if building a new list, append instead of print
        integer_counts.subtract((x, y))
在2.7中添加了

collections.Counter。对于早期版本,您需要使用defaultdict代替。它并不复杂得多。

我认为这比@roippi发布的itertools.combinations版本更难阅读,但如果整数列表很大,它应该会快得多。我通常重视人类在执行它的机器时间内读取代码的时间,但是哪些考虑获胜将取决于您的具体情况。

itertools版本不同,除非两个元素都重复,否则不会返回重复对。 EG,考虑[4,3,6,6]列表。 itertools版本将生成两个不同的(4,6)对并将它们返回;这个版本一旦与前6个匹配就会考虑消耗4,并且只返回一个。如果需要重复,set而不是Counter会起作用 - 尽管5的特殊情况会变得更复杂,除非你像@ lollercoaster的答案中所示迭代地构建集合。

答案 5 :(得分:0)

lst = [5,2,3,9,1]

lstLen = len(lst)

pair = 0

for i in range(lstLen):

    for j in range(lstLen):
        if(j <= i ): continue
        if((lst[i] + lst[j]) == 10):
            pair +=1
            print "[%s, %s]" % (lst[i], lst[j])

print "number of pair = %s" % pair

答案 6 :(得分:0)

#for unsorted array - complexity O(n)

def twoSum(arr, target):
  hash = {}

  if len(arr) < 2:
    return None

  for i in range(len(arr)):
    if arr[i] in hash:
      return [hash[arr[i]], i]
    else:
      hash[target - arr[i]] = i
  return None

twoSum([3,2,8,6],11)