Python中的子集递归求和

Python中的子集递归求和,python,recursion,dynamic-programming,memoization,subset-sum,Python,Recursion,Dynamic Programming,Memoization,Subset Sum,我很乐意得到一些帮助 我有以下问题: 我得到了一个数字列表和一个目标数字,我需要写两件事: 一种递归解决方案,如果子序列的和等于目标数,则返回True,否则返回False。 例如: subset_sum([-1,1,5,4],0) # True subset_sum([-1,1,5,4],-3) # False 其次,我需要使用我在上一个解决方案中编写的内容编写一个解决方案 但是现在使用了一个字典的Memonization,其中的键是元组: (len(seq),target) 对于1号

我很乐意得到一些帮助

我有以下问题:

我得到了一个数字列表和一个目标数字,我需要写两件事:

  • 一种递归解决方案,如果子序列的和等于目标数,则返回
    True
    ,否则返回
    False
    。 例如:

    subset_sum([-1,1,5,4],0)   # True
    subset_sum([-1,1,5,4],-3)  # False
    
  • 其次,我需要使用我在上一个解决方案中编写的内容编写一个解决方案 但是现在使用了一个字典的Memonization,其中的键是元组:
    (len(seq),target)

  • 对于1号,这是我到目前为止得到的:

    def subset_sum(seq, target):
        if target == 0: 
            return True
        if seq[0] == target:
            return True
        if len(seq) > 1:
            return subset_sum(seq[1:],target-seq[0]) or subset_sum(seq[1:],target)
        return False
    
    我不确定我是否做对了,所以如果我能得到一些意见,我将不胜感激

    2号:

    def subset_sum_mem(seq, target, mem=None ):
        if not mem:
            mem = {}
        key=(len(seq),target)
        if key not in mem:
            if target == 0 or seq[0]==target:
                mem[key] = True
            if len(seq)>1:
                mem[key] = subset_sum_mem(seq[1:],target-seq[0],mem) or subset_sum_mem(seq[1:],target,mem)
            mem[key] = False
    
        return mem[key]
    
    我无法得到回忆录给我正确的答案,所以我很高兴在这里得到一些指导


    谢谢所有愿意帮忙的人

    我修改了这个代码:

    def subset_sum(seq, target):
        left, right = seq[0], seq[1:]
        return target in (0, left) or \
            (bool(right) and (subset_sum(right, target - left) or subset_sum(right, target)))
    
    def subset_sum_mem(seq, target, mem=None):
        mem = mem or {}
        key = (len(seq), target)
        if key not in mem:
            left, right = seq[0], seq[1:]
            mem[key] = target in (0, left) or \
                (bool(right) and (subset_sum_mem(right, target - left, mem) or subset_sum_mem(right, target, mem)))
        return mem[key]
    

    你能提供一些不适用的测试用例吗?

    这就是我编写
    子集的方法

    def subset_sum(seq, target):
        if target == 0:
            return True
    
        for i in range(len(seq)):
            if subset_sum(seq[:i] + seq[i+1:], target - seq[i]):
                return True
        return False
    
    它使用了几个例子:

    >>> subset_sum([-1,1,5,4], 0))
    True
    >>> subset_sum([-1,1,5,4], 10)
    True
    >>> subset_sum([-1,1,5,4], 4)
    True
    >>> subset_sum([-1,1,5,4], -3)
    False
    >>> subset_sum([-1,1,5,4], -4)
    False
    
    老实说,我不知道如何回忆它

    旧的编辑:我用
    any()删除了解决方案
    ,因为在一些测试之后,我发现这会更慢

    更新:出于好奇,您还可以使用:


    在某些情况下,这比动态规划方法做得更好,但在另一些情况下,它会挂起(无论如何比递归方法更好)。

    仅供参考,这里有一个使用动态规划的解决方案:

    def positive_negative_sums(seq):
        P, N = 0, 0
        for e in seq:
            if e >= 0:
                P += e
            else:
                N += e
        return P, N
    
    def subset_sum(seq, s=0):
        P, N = positive_negative_sums(seq)
        if not seq or s < N or s > P:
            return False
        n, m = len(seq), P - N + 1
        table = [[False] * m for x in xrange(n)]
        table[0][seq[0]] = True
        for i in xrange(1, n):
            for j in xrange(N, P+1):
                table[i][j] = seq[i] == j or table[i-1][j] or table[i-1][j-seq[i]]
        return table[n-1][s]
    
    def正/负和(seq):
    P、 N=0,0
    对于下文中的e:
    如果e>=0:
    P+=e
    其他:
    N+=e
    返回P,N
    def子集_和(顺序,s=0):
    P、 N=正和/负和(序号)
    如果不是seq或sP:
    返回错误
    n、 m=len(seq),P-n+1
    表=[[False]*m表示x范围内的x(n)]
    表[0][seq[0]]=True
    对于x范围内的i(1,n):
    对于X范围内的j(N,P+1):
    表[i][j]=序号[i]==j或表[i-1][j]或表[i-1][j-seq[i]]
    返回表[n-1][s]
    
    您不只是在使用的任何原因?可能是因为这是家庭作业;)如果这实际上是家庭作业,请标记为家庭作业。人们仍然会提供帮助。这是一个很好的形式,可以帮助人们了解你来自哪里。它工作得很好!非常感谢你。为了深入了解解决方案,您能解释一下回流线的作用吗?返回target in(0,left)或\(bool(right)和(subset_sum(right,target-left)或subset_sum(right,target)),如果这是家庭作业,那么您应该弄清楚它是如何工作的——以及它与原始代码的相同之处。我唯一不明白的是bool(right)对解决方案给出了什么。你能解释一下吗?嗯。在我的实验中,我得到了
    []
    作为某个点的返回值,因此我将
    向右
    转换为布尔值。现在我想不出一个需要它的例子。将
    bool(right)
    更改为
    right
    ,然后尝试:
    subset\u sum([2],1)
    subset\u sum\u mem([2],1)
    subset\u sum=lambda seq,target:=0)或任意(subset\u sum(seq[:I]+seq[I+1:],target-v)对于I,v在枚举(seq)中,对于我们受虐狂者;
    )在这种情况下,记忆化实际上是一个微不足道的字典查找。很好的解决方案!或者:`return any(subset_sum(seq[:i]+seq[i+1:],target-seq[i])for i in range(len(seq))`@user1123417:不客气,如果你发现它有用,你可以投票(作为对我们努力的奖励),如果它是解决问题最有用的,你也可以接受它(左边的绿色箭头):)非常好。备选方案:
    def正数\负数\和(seq):返回和(如果e>=0,则e表示和),和(如果e<0,则e表示和)
    def positive_negative_sums(seq):
        P, N = 0, 0
        for e in seq:
            if e >= 0:
                P += e
            else:
                N += e
        return P, N
    
    def subset_sum(seq, s=0):
        P, N = positive_negative_sums(seq)
        if not seq or s < N or s > P:
            return False
        n, m = len(seq), P - N + 1
        table = [[False] * m for x in xrange(n)]
        table[0][seq[0]] = True
        for i in xrange(1, n):
            for j in xrange(N, P+1):
                table[i][j] = seq[i] == j or table[i-1][j] or table[i-1][j-seq[i]]
        return table[n-1][s]