Python 递归程序,以获得所有子集与给定的总和包括重复

Python 递归程序,以获得所有子集与给定的总和包括重复,python,recursion,Python,Recursion,我正在尝试编写一个以以下内容作为输入的程序: 允许的号码列表(arr) 总计(总和) 它应该返回arr中所有可能的数字组合,这些数字加起来等于sum 这就是我到目前为止所做的: def printAllSubsetsRec(arr, v, sum): if sum == 0: return [v] if len(arr) == 0: return v1 = [] + v v1.append(arr[0]) without

我正在尝试编写一个以以下内容作为输入的程序:

  • 允许的号码列表(
    arr
  • 总计(
    总和
  • 它应该返回
    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数组_和(arr:Set[int],target:int)->List[List[int]:
    最小值=最小值(arr)
    def go(
    正在进行中:List[Tuple[List[int],int]],
    完成:列表[列表[int]]
    )->List[List[int]]:
    现在正在进行中,新完成=[],[]
    对于分支机构,汇总进行中:
    对于arr中的i:
    #任何低于“目标值”小于“最小值”的值都会超出目标值
    如果总和+列表[列表[int]]:
    def go(acc:List[List[int]])->List[List[int]]:
    进行中=[
    分支机构+[i]
    行政协调会分部
    因为我在arr
    如果总和(分支)<目标
    ]
    完成=[acc中分支的分支如果总和(分支)=目标]
    如果未进行,则返回完成,否则继续(进行中+完成)
    返回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)))
    

    这个问题是一种划分问题。尽管它是
    NP难
    ,但您可以使用
    动态编程
    pseuso多项式时间
    内求解。如果列表中的数字重复,是否要复制输出。e、 g.
    [1,3,5,5],5
    是否包含两份
    [5]
    ?或者换句话说,我们可以假设
    arr
    是一个集合吗?@JoelBerkeley是的,我们可以假设
    arr
    是一个集合。
    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]]