**问题:**给你一个非负整数数组 nums
和一个整数 target
。 向数组中的每个整数前添加 '+'
或 '-'
,然后串联起所有整数,可以构造一个 表达式 :
- 例如,
nums = [2, 1]
,可以在2
之前添加**'+'
** ,在1
之前添加**'-'
** ,然后串联起来得到表达式"+2-1"
。
返回可以通过上述方法构造的、运算结果等于**target
** 的不同 表达式 的数目。
方法1:
深度优先搜索
看到题目容易想到的就是dfs 暴力枚举每一个元素,每个元素都存在两种情况:
1、为正数 --> 加上之前枚举的情况
2、为负数 --> 减去之前枚举的情况
最后当枚举到最后一个元素时判断是否满足条件,满足**+1** ,不满足 +0 。
C语言代码:
cpp
int dfs(int *nums,int i,int numsSize,int sum,int target){
if(i == numsSize){// 递归完毕
if(sum == target) return 1;// 符合条件+1
else return 0;// 不符合
}
// 还没递归到最后,两种情况相加
return dfs(nums,i + 1,numsSize,sum + nums[i],target) + dfs(nums,i + 1,numsSize,sum - nums[i],target);
}
int findTargetSumWays(int* nums, int numsSize, int target) {
return dfs(nums,0,numsSize,0,target);
}
C++代码:
cpp
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int n = nums.size();
auto dfs = [&](auto &&dfs,int i,int sum){
if(i == n){
if(sum == target) return 1;
else return 0;
}
return dfs(dfs,i + 1,sum + nums[i]) + dfs(dfs,i + 1,sum - nums[i]);
};
return dfs(dfs,0,0);
}
};
符号不是正就是负。设所有数字和为 s ,正数和为 p ,负数的绝对值和为 q 。所以 s = p + q 。又因为目标是 target ,所以p - q = targe t ;合并两个式子,得到 2q = s - target 。所以要求负数的绝对值和为**(s - target)/ 2** ,即为背包容量。
代码:
cpp
int findTargetSumWays(int* nums, int numsSize, int target) {
int sum = 0,i = numsSize;
while(i--) sum += nums[i];// 求和
int c = sum - target;
if(c < 0 || c % 2) return 0;
c /= 2;// 背包容量
int memo[c + 1];// +1是为了数组标号对应上
memset(memo, 0, sizeof(memo));
memo[0] = 1;
for(i = 0;i < numsSize;i++)
for(int j = c;j >= nums[i];j--) memo[j] += memo[j - nums[i]];
return memo[c];
}