- 思路
这道题一样有重叠子问题,然后我们看到它有一个target,一个数组,数组里的数字只能用一次,所以考虑01背包问题求解。
这道题,要找到所有的情况,就是要穷举,也可想到回溯的办法来穷举所有的情况。
target就是背包的最大容量,然后数组nums[i]加上符号一起构成了物品的重量和物品的价值。
考虑dp五要素:
dp的数组定义与下标含义:dp[target+1],代表对应的背包容量下满足价值等于,其中下标含义是背包容量;
dp的状态转移方程:dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);
dp的初始化:都初始化为0;
dp的遍历顺序:外层物品i=0;i<nums.length;i++,内层背包容量j=target;j>=nums[i];j–;
举例推导
考虑到这里就发现困难了,上述感觉不太对。
参考题解
这里最难的是想到有加有减,怎么来处理呢?如果只有加或减一种是不是就更好处理呢?
所以依旧是考虑把加减分为两部分。
class Solution {
public int findTargetSumWays(int[] nums, int target) {
int sum = 0;
// 求总和
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
// 这是推导出的为+的数字的总和
// 要满足bagSize = (sum + target) / 2,如果不能够整除说明数字是凑不上的
if ((sum + target) % 2 == 1) {
return 0;
}
// 如情况[100] -200
if (Math.abs(target) > sum) {
return 0;
}
// 要得到的总和,即添加+得到的总和
int bagSize = (sum + target) / 2;
int[] dp = new int[bagSize + 1];
dp[0] = 1;
for (int i = 0; i < nums.length; i++) {
for (int j = bagSize; j >= nums[i]; j--) {
dp[j] += dp[j - nums[i]];
}
}
return dp[bagSize];
}
}
- 总结
其实到这里,发现背包问题很多时候都不是能够直接就能想到办法来解决,很多时候都是要处理一下,分为子问题,变成两部分,拿一部分来做背包去与另一部分进行相应的呼应。
这道题又是一种新的题型是在背包中加入组合问题,在dp数组定义和状态转移方程就有所区别。
还需要多加练习。