494.目标和
🎯494.目标和
给你一个整数数组 nums 和一个整数 target 。
向数组中的每个整数前添加 ‘+’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 :
例如,nums = [2, 1] ,可以在 2 之前添加 ‘+’ ,在 1 之前添加 ‘-’ ,然后串联起来得到表达式 “+2-1” 。 返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。
思路
基本思想
由于需要最终获得target,肯定是一部分数为正一部分数为负,那么我们可以先将target拿出来,剩下的数等分成两半,一半为正一半为负,这样相加抵消肯定为0,对target没有影响
将target拿出来之后剩下的数记为sum-target
,其中sum是nums求和得到的,之后将sum-target
分成两半得到的数为:
$$
capacity=\frac{sum-target}{2}
$$
capacity作为背包的容量,然后看nums中有哪些方案可以将背包刚好填满,记录这些方案数即可
现在的问题就是如何记录所有的方案数,dp[j]代表和为j的方案数
- 已经有一个1(nums[i]) 的话,有 dp[4]种方法 凑成 容量为5的背包。
- 已经有一个2(nums[i]) 的话,有 dp[3]种方法 凑成 容量为5的背包。
- 已经有一个3(nums[i]) 的话,有 dp[2]中方法 凑成 容量为5的背包
- 已经有一个4(nums[i]) 的话,有 dp[1]中方法 凑成 容量为5的背包
- 已经有一个5 (nums[i])的话,有 dp[0]中方法 凑成 容量为5的背包
将上面的情况累加,所以最终的公式为:
$$
dp[j] += dp[j - nums[i]]
$$
可以理解为依次向当前背包中放入nums[i]
,剩下的dp[j-nums[i]]
继续求解方案数,不同的nums[i]
形成了不同的方案数,所以需要累加
注意有两种情况问题无解
- 数组求和都小于target,肯定无法形成target
- 按照公式1求解的capacity不是整数,数组中的数组合都是整数,不符合要求
相当于找出那些数加负号,剩下的数都加正号,正负抵消之后就形成了最终的target
执行流程
计算背包容量
初始化dp数组,要记住dp数组的含义
所以
dp[0]=1
计算01背包(形成负数的方案数)
返回结果
代码
根据以上分析,得出以下代码:
|
|
总结
要想形成target,肯定会剩下一部分sum-target,这部分干扰项需要去除,去除的过程中不能对target造成任何影响,所以想到了分成两半,一半正数一半负数,此数作为背包的容量
此时只需要从集合中找出所有的能将背包刚好填满的方案即可
本题中的dp数组含义与之前的不一样,本题中dp[j]代表同号数字组合得到j的所有方案数,所以dp是由前面的方案数累加得到的