Python 查找具有给定和的数字列表的所有组合

Python 查找具有给定和的数字列表的所有组合,python,algorithm,python-3.x,combinations,subset-sum,Python,Algorithm,Python 3.x,Combinations,Subset Sum,我有一个数字列表,例如 numbers = [1, 2, 3, 7, 7, 9, 10] 如您所见,数字可能会在该列表中出现多次 我需要得到这些数字的所有组合,它们有一个给定的和,例如10 组合中的项目可能不会重复,但编号中的每个项目必须单独处理,这意味着列表中的两个7代表具有相同值的不同项目 顺序并不重要,因此[1,9]和[9,1]是相同的组合 组合没有长度限制,[10]与[1,2,7]一样有效 如何创建符合上述条件的所有组合的列表? 在本例中,它将是[[1,2,7],[1,2,7],[1,

我有一个数字列表,例如

numbers = [1, 2, 3, 7, 7, 9, 10]
如您所见,数字可能会在该列表中出现多次

我需要得到这些数字的所有组合,它们有一个给定的和,例如
10

组合中的项目可能不会重复,但编号中的每个项目必须单独处理,这意味着列表中的两个
7
代表具有相同值的不同项目

顺序并不重要,因此
[1,9]
[9,1]
是相同的组合

组合没有长度限制,
[10]
[1,2,7]
一样有效

如何创建符合上述条件的所有组合的列表?


在本例中,它将是
[[1,2,7],[1,2,7],[1,9],[3,7],[3,7],[10]

您可以使用itertools对每个可能大小的每个组合进行迭代,并过滤掉不等于10的所有内容:

import itertools
numbers = [1, 2, 3, 7, 7, 9, 10]
result = [seq for i in range(len(numbers), 0, -1) for seq in itertools.combinations(numbers, i) if sum(seq) == 10]
print result
结果:

[(1, 2, 7), (1, 2, 7), (1, 9), (3, 7), (3, 7), (10,)]

不幸的是,这有点像O(2^N)复杂性,因此它不适用于大于(比如)20个元素的输入列表。

这个问题以前有人问过,请参阅@msalvadores答案。我更新了在python 3中运行的python代码:

def subset_sum(数字、目标、部分=[]):
s=总和(部分)
#检查部分和是否等于目标值
如果s==目标:
打印(“总和(%s)=%s”%(部分,目标))
如果s>=目标:
return#如果我们达到了这个数字,为什么还要继续呢
对于范围内的i(len(数字)):
n=数字[i]
剩余=数字[i+1:]
子集_和(剩余、目标、部分+[n])
如果名称=“\uuuuu main\uuuuuuuu”:
子集和([3,3,9,8,4,5,7,10],15)
#产出:
#总和([3,8,4])=15
#总和([3,5,7])=15
#总和([8,7])=15
#总和([5,10])=15
虽然它很棒,但我认为它作为一个生成器更有用:

def subset_sum(numbers, target, partial=[], partial_sum=0):
    if partial_sum == target:
        yield partial
    if partial_sum >= target:
        return
    for i, n in enumerate(numbers):
        remaining = numbers[i + 1:]
        yield from subset_sum(remaining, target, partial + [n], partial_sum + n)
列表(子集和([1,2,3,7,7,9,10,10])
产生
[[1,2,7],[1,2,7],[1,9],[3,7],[3,7],[10]]
这是有效的

from itertools import combinations


def SumTheList(thelist, target):
    arr = []
    p = []    
    if len(thelist) > 0:
        for r in range(0,len(thelist)+1):        
            arr += list(combinations(thelist, r))

        for item in arr:        
            if sum(item) == target:
                p.append(item)

    return p
@卡西马尔巴卡利

这可能不是该帖子所要寻找的,但如果你想:

查找一系列数字[lst]的所有组合,其中每个lst包含N个元素,总计为K:使用此选项:

# Python3 program to find all pairs in a list of integers with given sum  
from itertools import combinations 

def findPairs(lst, K, N): 
    return [pair for pair in combinations(lst, N) if sum(pair) == K] 

#monthly cost range; unique numbers
lst = list(range(10, 30))
#sum of annual revenue per machine/customer
K = 200
#number of months (12 - 9 = num months free)
N = 9

print('Possible monthly subscription costs that still equate to $200 per year:')
#print(findPairs(lst, K, N)) 
findPairs(lst,K,N)
结果:

Possible monthly subscription costs that still equate to $200 per year:
Out[27]:
[(10, 11, 20, 24, 25, 26, 27, 28, 29),
 (10, 11, 21, 23, 25, 26, 27, 28, 29),
 (10, 11, 22, 23, 24, 26, 27, 28, 29),

这背后的想法/问题是“如果我们提供x个月的免费服务,但仍能达到收入目标,我们每月能收取多少费用?”.

如果您在理解上述代码时感到困惑,这里是上述代码的一个简单版本,适用于范围(1,len(a)):适用于itertools中的s。组合(a,i):如果总和=sum1:print(s)这个代码有时间复杂度更小的版本吗?@Kevin:对于更多的元素,如何处理它?
itertools。如果
number
有重复的元素,组合将创建重复的元素。你能解释一下“从子集的收益率求和(剩余,目标,部分+[n],部分求和+n)”这一行吗@Martin Valgur:它能处理10000个列表元素吗?如果列表中的元素不完全相同,这将创建重复的元素。如果您希望每个输出包含一定数量的数字,比如12,该怎么办。每个列表需要有12个数字,总和为15?@max我正在寻找一个类似于您的解决方案,您找到什么了吗?@qasimalbaqali我找到了。不要介意我的评论,但这是可行的:#Python3程序从itertools导入组合def findPairs(lst,K,N)中查找具有给定和的整数列表中的所有对:返回[pair for pair in compositions(lst,N),如果和(对)=K]#每月成本范围;唯一数字lst=列表(范围(10,30))#每台机器/客户的年收入之和K=200#月数(12-9=免费月数)N=9打印('可能的每月订阅成本仍然等于每年200美元:')#打印(findPairs(lst,K,N))findPairs(lst,K,N)