Python 给定一个数字列表,有多少种不同的方法可以将它们相加得到一个总和S?

Python 给定一个数字列表,有多少种不同的方法可以将它们相加得到一个总和S?,python,combinations,permutation,Python,Combinations,Permutation,给定一个数字列表,有多少种不同的方法可以将它们相加得到一个总和S 例如: 列表=[1,2] S=5 1) 1+1+1+1+1=5 2) 1+1+1+2=5 3) 1+2+2=5 4) 2+1+1+1=5 5) 2+2+1=5 6) 1+2+1+1=5 7) 1+1+2+1=5 8) 2+1+2=5 答案=8 这是我尝试过的,但它只输出3作为答案 lst = [1, 2] i = 1 result = 0 while i <= 5: s_list = [sum(comb) for c

给定一个数字列表,有多少种不同的方法可以将它们相加得到一个总和S

例如:

列表=[1,2]

S=5

1) 1+1+1+1+1=5

2) 1+1+1+2=5

3) 1+2+2=5

4) 2+1+1+1=5

5) 2+2+1=5

6) 1+2+1+1=5

7) 1+1+2+1=5

8) 2+1+2=5

答案=8

这是我尝试过的,但它只输出3作为答案

lst = [1, 2]
i = 1
result = 0
while i <= 5:
    s_list = [sum(comb) for comb in combinations_with_replacement(lst, i)]
    for val in s_list:
        if val == 5:
            result += 1
    i+= 1

print(result)
lst=[1,2]
i=1
结果=0

当i时,您希望使用递归遍历加法的每个阶段的每个可能性,并在达到预期值后返回使用的数字

def find_addend_combinations(sum_value, addend_choices, base=0, history=None):
    if history is None: history = []

    if base == sum_value:
        return tuple(history)
    elif base > sum_value:
        return None
    else:
        results = []
        for v in addend_choices:
            r = find_addend_combinations(sum_value, addend_choices, base + v,
                                         history + [v])
            if isinstance(r, tuple):
                results.append(r)
            elif isinstance(r, list):
                results.extend(r)
        return results

您可以将最后一部分写为列表理解,但我认为这种方式更清晰。

同时使用
itertools。使用替换的组合和
置换的组合:

import itertools

l = [1,2]
s = 5

res = []
for i in range(1, s+1):
    for tup in itertools.combinations_with_replacement(l, i):
        if sum(tup) == s:
            res.extend(list(itertools.permutations(tup, i)))
res = list(set(res))

print(res)
[(1, 2, 2),
 (2, 2, 1),
 (1, 1, 2, 1),
 (1, 2, 1, 1),
 (2, 1, 1, 1),
 (1, 1, 1, 2),
 (2, 1, 2),
 (1, 1, 1, 1, 1)]

print(len(res))
# 8

具有不同顺序元素的组合被视为等效。例如,如果您只讨论组合,则总和列表中的#3和#5被认为是等效的

相反,排列是两个集合唯一的,如果它们由不同的顺序由相同的元素组成。

为了得到你想要的答案,你需要将这两个概念结合起来

  • 首先,使用您的技术找到符合您标准的组合
  • 接下来,排列组合中的数字集合
  • 最后,在一个集合中收集生成的排列以删除重复项
  • [01]中的[ins]:def组合_生成器(数字、k、目标): …:断言k>0,“必须是正数;'k={}”。格式(k) …:assert len(numbers)>0,“数字列表必须至少有一个元素” ...: …:在( …:{'numbers':组合,'sum':和(组合)} …:用于范围(1,k+1)中的num_元素 …:用于itertools中的组合。使用替换的组合(数字、num元素) ...: ): …:如果候选人['sum']!=目标: …:继续 …:用于itertools中的置换_候选者。置换(候选者['number']): …:产量置换候选 ...: [ins]In[02]:{组合_生成器([1,2],5,5)中的候选者的候选者} 出[02]: {(1, 1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 2, 1), (1, 2, 1, 1), (1, 2, 2), (2, 1, 1, 1), (2, 1, 2), (2, 2, 1)}
    使用动态规划怎么样?我相信它更容易理解,也更容易实现

    def cal(target, choices, record):
    
        min_choice = min(choices)
        if min_choice > target:
            return False
    
        for i in range(0, target+1):
            if i == 0:
                record.append(1)
            elif i < min_choice:
                record.append(0)
            elif i == min_choice:
                record.append(1)
            else:
                num_solution = 0
                j = 0
                while j < len(choices) and i-choices[j] >= 0:
                    num_solution += record[i-choices[j]]
                    j += 1
                record.append(num_solution)
    
    
    choices = [1, 2]
    record = []
    cal(5, choices, record)
    print(record)
    print(f"Answer:{record[-1]}")
    
    def-cal(目标、选项、记录):
    最小选择=最小(选择)
    如果最小选择>目标:
    返回错误
    对于范围内的i(0,目标+1):
    如果i==0:
    记录。追加(1)
    elif i<最小选择:
    记录。追加(0)
    elif i==最小选择:
    记录。追加(1)
    其他:
    num_解决方案=0
    j=0
    当j=0时:
    num_solution+=记录[i-choices[j]]
    j+=1
    record.append(num\u解决方案)
    选项=[1,2]
    记录=[]
    cal(5,选择,记录)
    打印(记录)
    打印(f“答案:{record[-1]}”)
    
    这里的核心思想是使用一个额外的
    record
    数组来记录可以找到多少方法来获取当前num,例如
    record[2]=2
    意味着我们可以使用多种方法来获取
    2
    1+1
    2
    )的总和

    我们有
    record[target]=sum(record[target choices[i]])
    其中
    i
    迭代选择。试着想想,获得
    sum=5
    的方式必须与获得
    sum=4
    的方式相关,依此类推。

    使用

    我们假设您的列表由
    [1,2,5]
    组成,因此我们有这个递归函数:

    f(n[1,2,5])=f(n-1[1,2,5])+f(n-2[1,2,5])+f(n-5[1,2,5])

    因为如果总和中的第一个数字是
    1
    ,那么剩下的就有
    f(n-1,[1,2,5])
    选项,如果是
    2
    ,剩下的就有
    f(n-2,[1,2,5])
    选项,依此类推

    因此,从
    f(1)
    开始,用动态规划来解决问题。在最坏的情况下,这个解决方案是
    O(n^2)
    ,当列表中有
    O(n)
    项时,就会出现这种情况

    解决方案如下:

    answers = []
    lst = [1,2]
    number = 5
    def f(target):
      val = 0
      for i in lst:               #O(lst.count())
        current = target - i
        if current > 0:
          val += answers[current-1]
      if lst.__contains__(target): #O(lst.count())
        val += 1
      answers.insert(target,val)
    
    j = 1;
    while j<=number:  #O(n) for while loop
      f(j)
      j+=1
    
    print(answers[number-1])
    
    answers=[]
    lst=[1,2]
    数字=5
    def f(目标):
    val=0
    对于lst中的i:#O(lst.count())
    电流=目标-i
    如果当前>0:
    val+=答案[当前-1]
    如果lst.uu包含(目标):#O(lst.count())
    val+=1
    答案。插入(目标,val)
    j=1;
    
    如果搜索短语“Python sum to target”,jTry
    permutations
    而不是
    compositions\u with\u replacement
    ,您会找到比我们在这里的答案更好的资源来解释它。@pault我如何将它用于置换?你能举个例子吗?这看起来不错,但我认为如果
    l
    的项目在大小上接近
    s