Python 给定一个数字列表,有多少种不同的方法可以将它们相加得到一个总和S?
给定一个数字列表,有多少种不同的方法可以将它们相加得到一个总和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作为答案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
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”,jTrypermutations
而不是compositions\u with\u replacement
,您会找到比我们在这里的答案更好的资源来解释它。@pault我如何将它用于置换?你能举个例子吗?这看起来不错,但我认为如果l
的项目在大小上接近s