视频讲解:https://www.bilibili.com/video/BV1o8411j73x
https://programmercarl.com/0494.%E7%9B%AE%E6%A0%87%E5%92%8C.html
1.本题或者说类似01背包问题的解法都是先找到能将背包分成两部分的这个中间值就是我们要求的每层都需要遍历的背包最大容量,至少目前我是这么理解的,本题也是遵循这个规律,要求求出符合要求的搭配方案,由于题要求添加+ - 号来求出结果。我们将数据分成两堆,一堆是都是加法的数据,一堆都是减法的数据,我们通过这两堆数据结合已知条件就可以解出第一等式这里借用代码随想录的片段
本题要如何使表达式结果为target,
既然为target,那么就一定有 left组合 – right组合 = target。
left + right = sum,而sum是固定的。right = sum – left
left – (sum – left) = target 推导出 left = (target + sum)/2 。
target是固定的,sum是固定的,left就可以求出来。
此时问题就是在集合nums中找出和为left的组合。
所以是要求我们去找寻到left组合的所有情况,也就说left就是我们这个题所要求的最大容量的背包,使用滑动数组来迭代求出本题的结果,本题还是以直观的二维数组的更容易解决该问题,结合这画图(二维数组的手动推出的结果图)情况1.就是当不放入本层循环的数据的时候就是dp[i - 1][j],情况二就是放入该数据但是先出来不放入的情况但减去放入所消耗的空间(tips:这个地方是本题的数据既是重量也是价值)所以是 dp[i - 1][j - nums[i]]这样就讨论好两个动态规划出本层循环要求出的值了。
总结一下,动态规划至少到我坐到这里的题的时候,我的理解就是想要将题目想到01背包问题,就将数据分为两个部分,求其中一个部分(背包最大容量)的解法,同样重要的是dp数组的含义以及初始化的操作,每一个部分都要考虑完整,同时最重要的就是递归公式,这个部分更好的方式是结合着二维数组的方式在脑海里模拟这个数组的数据的情况,更好的理解将其压缩成为一维滑动数组也能够更好理解。
CPP
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
if(nums.size() == 0)return 0;
int sum = 0;
for(int i = 0; i < nums.size(); i++){
sum += nums[i];
}
int left = (sum + target) / 2;
if((sum + target) % 2 == 1)return 0;
if(abs(target) > sum)return 0;
vector<int> dp(left + 1, 0);
dp[0] = 1;
for(int i = 0; i < nums.size(); i++){
for(int j = left; j >= nums[i]; j--){
dp[j] += dp[j - nums[i]];
}
}
return dp[left];
}
};