[英]Recursive program to get all subsets with given sum includes repetitions
我正在尝试编写一个作为输入的程序:
arr
) sum
) 它应该返回arr
中所有可能的数字组合,加起来sum
。
这是我到目前为止:
def printAllSubsetsRec(arr, v, sum):
if sum == 0:
return [v]
if len(arr) == 0:
return
v1 = [] + v
v1.append(arr[0])
without_first = printAllSubsetsRec(arr[1:], v, sum)
with_first = printAllSubsetsRec(arr[1:], v1, sum - arr[0])
if with_first and without_first:
return with_first + without_first
elif with_first:
return with_first
elif without_first:
return without_first
def array_sums(arr, sum):
v = []
return printAllSubsetsRec(arr, v, sum)
问题是它不会返回包括重复在内的所有子集。
例如:
print(array_sums([1,3,5],5))
# [[1, 1, 1, 1, 1], [1, 1, 3], [1, 3, 1], [3, 1, 1], [5]]
我怎样才能做到这一点?
在每次递归时,我为arr
每个数字创建了一个新分支。 我保留了总和与目标相匹配的分支,并停止探索总和超过目标的分支。
更快 (通过调用链传递分支的累计总和)
def array_sums(arr: Set[int], target: int) -> List[List[int]]:
smallest = min(arr)
def go(
in_progress: List[Tuple[List[int], int]],
complete: List[List[int]]
) -> List[List[int]]:
now_in_progress, newly_complete = [], []
for branch, sum_ in in_progress:
for i in arr:
# anything short of `target` by less than `smallest` will overshoot
if sum_ + i <= target - smallest:
now_in_progress.append((branch + [i], sum_ + i))
elif sum_ + i == target:
newly_complete.append(branch + [i])
newly_complete += complete
return newly_complete if not now_in_progress else go(
now_in_progress, newly_complete
)
return go([([], 0)], [])
更简单和纯粹的功能 (计算每次递归时分支的总和)
def array_sums(arr: Set[int], target: int) -> List[List[int]]:
def go(acc: List[List[int]]) -> List[List[int]]:
in_progress = [
branch + [i]
for branch in acc
for i in arr
if sum(branch) < target
]
complete = [branch for branch in acc if sum(branch) == target]
return complete if not in_progress else go(in_progress + complete)
return go([[]])
您可以使用生成器的递归:
def subsets(arr, _sum, c = []):
if sum(c) == _sum:
yield c
else:
for i in arr:
if sum(c+[i]) <= _sum:
yield from subsets(arr, _sum, c+[i])
print(list(subsets([1,3,5], 5)))
输出:
[[1, 1, 1, 1, 1], [1, 1, 3], [1, 3, 1], [3, 1, 1], [5]]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.