leetcode494. 目标和python-01背包问题篇

题目
给你一个整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 ‘+’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 ‘+’ ,在 1 之前添加 ‘-’ ,然后串联起来得到表达式 “+2-1” 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

示例 1:

输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 3 。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3
示例 2:

输入:nums = [1], target = 1
输出:1

思路和代码

唉,就完全没思路嘛!动态规划,那dp[i]表示值为i的表达式种类数,那dp[i]能有什么推导出来呢?和dp[i-1]有什么关系呢?dp[0]为0?

看了题解,刚开始有点绕,差点没绕过来。吃过饭一看,懂了。

例如nums=[1,1,1,1,1],里面的每个1在表达式中可能是+1,也可能是-1。首先这个数组的和为sum_value=sum(nums),那么假设在表达式中正数的和为x,那么负数的和为-(sum_value-x)。又因为正数的和+负数的和=target。所以就有x-(sum_value-x)=target,也就是x=(target+sum_value)/2。

怎么是一个背包问题呢?这里面的容量就是x,物品就是数组nums里面的数,而且每一个数只能放一次。那怎么解决每个数可能是正可能是负的问题呢?因为x是正数的和,所以只要考虑若干个整数把容量x装满即可。

首先有两种情况直接返回0。一种情况是如果x不是整数,另一种情况是target的绝对值大于sum_value。所以这也保证了bagsize肯定是大于等于0的。

如何推导得到dp[i],以dp[4]为例。

有一个1的话,有dp[3]种方法凑成dp[4]
有一个2的话,有dp[2]种方法凑成dp[4]
有一个3的话,有dp[1]种方法凑成dp[4]
有一个4的话,有dp[0]中方法凑成dp[4]

根据这个例子也可以看出来,dp[0]的初始化应该为1。如果dp[0]为0,后面的全都为0了。
综上,代码如下:

class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        sum_value = sum(nums)
        if (target + sum_value)%2 or abs(target) > sum_value:
            return 0
        bagsize = (target + sum_value) // 2
        dp = [0] * (bagsize + 1)
        dp[0] = 1
        for i in range(len(nums)):
            for j in range(bagsize,nums[i]-1,-1):
                dp[j] += dp[j-nums[i]]
        return dp[bagsize]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值