新手在这里。 我有这段代码,它显示所有可能的总和以达到一定数量。 但是它的复杂性太高了,而当数字太高时它会花费很长时间。如何将其重构为更简单的内容?
import itertools
def combos(n):
result = []
for i in range(n,0,-1):
for seq in itertools.combinations_with_replacement(range(1,n+1), i):
if sum(seq) == n:
seq = list(seq)
result.append(seq)
return(result)
combos(4)
输出:
[[1,1,1,1],[1,1,2],[1,3],[2,2],[4]]
答案 0 :(得分:0)
递归版本可能是这样的:
def combinations_max_sum(sum_max, i_max=None):
if sum_max == 0:
return [()]
if not i_max or i_max > sum_max:
i_max = sum_max
combinations = [(i, *right_part)
for i in range(i_max, 0, -1)
for right_part in combinations_max_sum(sum_max-i, i_max=i)]
return combinations
测试:
print(combinations_max_sum(4)) # [(4,), (3, 1), (2, 2), (2, 1, 1), (1, 1, 1, 1)]
print(combinations_max_sum(4, i_max=1)) # [(1, 1, 1, 1)]
print(combinations_max_sum(5))
# [(5,), (4, 1), (3, 2), (3, 1, 1), (2, 2, 1), (2, 1, 1, 1), (1, 1, 1, 1, 1)]
分解问题的想法:一组组合可以写为一个数字,该数字与所有组合的和为n
减去第一个数字。
一个简单的无需重复处理的代码可能是这样的:
def combinations_with_repetition(n):
if n == 0:
return [()]
combinations = [(i, *right_part) # concatenation
for i in range(1, n+1) # for all possible first number
for right_part in combinations_with_repetition(n-i)]
# ^ all possible combinations
# given the first number i
return combinations
给出:
combinations_with_repetition(3)
# [(1, 2), (1, 1, 1), (2, 1), (3,)]
(1, 2)
和(2, 1)
是相似的,以防止添加i_max
参数(请参阅第一个函数)。这里的想法是始终按降序排列。右边的数字始终等于或小于左边的数字。该最大值作为参数传递,循环从该最大值开始,而不是要求的总和。