我正在尝试在整数列表中找到一个和的组合。
包含总和的数字量受变量限制,例如在列表中 -
[5,2,3,9,1],我想找到10的总和,只有2个数字。
这样程序就会打印出[9,1]。
我是python的新手,有一种简单的方法吗?
谢谢。答案 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)