目标和
| Category | Difficulty | Likes | Dislikes |
|---|---|---|---|
| algorithms | Medium (49.15%) | 1083 | - |
Tags
Companies
给你一个整数数组 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
提示:
1 <= nums.length <= 200 <= nums[i] <= 10000 <= sum(nums[i]) <= 1000-1000 <= target <= 1000
题解:
那么只要搞到nums[i]的话,凑成dp[j]就有dp[j - nums[i]] 种方法。
例如:dp[j],j 为5,
- 已经有一个1(nums[i]) 的话,有 dp[4]种方法 凑成 dp[5]。
- 已经有一个2(nums[i]) 的话,有 dp[3]种方法 凑成 dp[5]。
- 已经有一个3(nums[i]) 的话,有 dp[2]中方法 凑成 dp[5]
- 已经有一个4(nums[i]) 的话,有 dp[1]中方法 凑成 dp[5]
- 已经有一个5 (nums[i])的话,有 dp[0]中方法 凑成 dp[5]
那么凑整dp[5]有多少方法呢,也就是把 所有的 dp[j - nums[i]] 累加起来。
class Solution {
public:
//01背包的变形就是二分,要或者不要
//这里最重要的是找到背包的容量是多少
//把加法和减法分开,背包装的加的和或者减的和
//加的和x,减的和sum-x,x-(sum-x)=target,得到x=(target+sum)/2
//这道题变成了用dp求装满x的种类
//dp[i]的定义是i的容量内,有dp[i]种方法 ,而不是dp[i]表示最大加到的数最后统计,这样会没法统计
//dp[i]可以做选择,也可以用来统计
int findTargetSumWays(vector<int>& nums, int target) {
int sum = 0;
for (int i = 0; i < nums.size(); i++) sum += nums[i];
//去掉不存在的情况
if((sum+target)%2==1) return 0; //加起来的和必须是整数
//题目给出nums中的数都是正数,
if(sum<abs(target)) return 0; //全加或者全减都不够使
int x=(sum+target)/2;
vector<int> dp(x+1,0); //这里其实只用x的容量大小就够了,
dp[0]=1; //这个非常重要
for (int i = 0; i < nums.size(); i++){
for (int j = x; j>=nums[i]; j--)
{
dp[j]=dp[j-nums[i]]+dp[j]; //其实就是统计dp[j-nums[i]]的总数
}
}
return dp[x];
}
};
