【leetcode前500】494. 目标和

先考虑对称性,如果把示例的正负号颠倒一下,就是-3了,所以target只要是大于等于0的即可,先取个绝对值简化计算。

因此很容易想到特殊情况一:如果所有数字只和S都比target小,那返回0.

我们将前面带正号的数字和为Sp,带符号的为Sq,那么

S=Sp+Sq

并且

Sp-Sq=target

因此得到

Sq=(S-target)/2

我们知道要计算的数字都是整数,因此得到特殊情况2:(S-target)/2非正整数的返回0,也就是(S-target)%2==1的情况。

现在问题转化成Sq=(S-target)/2这个表达式,也就是”选出一组数字,能够和为Sq的情况有多少种"

转化成了01背包问题——每个数字都有选或者不选的情况,但是要装满容量为Sq的包。

如果用数组表示那如果原来的数字集合为[1,2]

那么dp=[1,1,1]表示空包1中方法,和为1一种方法,和为2也是一种方法。

如果加入考虑数字1,数字集合变成[1,2,1]

那么dp=[1,2,2,],因为dp[i]+=dp[i-n],也就是经由和为i-n的组合加上n就可以得到i,那么dp[i-n]表示的方法数就可以被加过来。

class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        s=sum(nums)
        target=abs(target)
        if s<target or (s-target)%2!=0:
            return 0
        target=(s-target)//2
        dp=[0]*(target+1)
        dp[0]=1
        for n in nums:
            for i in range(target,n-1,-1):
                dp[i]+=dp[i-n]
        return dp[-1]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值