这不妥妥的dfs吗。对每一位有两种情况+和-。一直到数组结尾再判断s是否等于0,如果等于0相当于有一种情况,res++。
class Solution {
public:
void dfs(vector<int>& nums, int index, int S){
if(index == nums.size()){
if(S == 0) res++;
return;
}
dfs(nums,index+1,S+nums[index]);
dfs(nums,index+1,S-nums[index]);
return;
}
int findTargetSumWays(vector<int>& nums, int S) {
//dfsordp
//dfs就是找一种可以实现的情况,dfs下一位两种情况,选或者不选,当遍历到最后一位了判断如果等于0就++并返回
//有大量重复计算,有点像01背包
//直接排除全加小于或者全减大于
int sum = 0, jian = 0;
for(int x:nums){
sum += x;
jian -= x;
}
if(sum < S || jian > S) return 0;
dfs(nums,0,S);
return res;
}
private:
int res = 0;
};
可以dfs,但是时间复杂度比较高。
我们考虑dp,我们找一组正数和为left,一组负数和为-right
left-right = S。left+right = sum。left-(sum-left)=S->left = (S+sum)/2
所以我们只要找和为(sum+S)/2,dp[j]就是前i位数字能组成i的情况,因为只和左上有关,一维从后往前遍历即可
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int S) {
int sum = 0;
for(int x:nums){
sum += x;
}
//left-right = S
//left+right = sum
//left-(sum-left)=S->left = (S+sum)/2
if(sum <S || (sum+S)%2 ==1) return 0;
int target = (sum+S)/2;
vector<int> dp(target+1);
//basecase:将装重量为0的背包设为1
dp[0] = 1;
//只和左上的状态有关系,一维从后往前遍历即可
for(int i = 0; i < nums.size(); ++i){
//防止越界控制j的大小
for(int j = target; j >= nums[i]; --j){
//只考虑正数
dp[j] += dp[j-nums[i]];
}
}
return dp[target];
}
};
dfs或者记忆化递归,因为这里dfs爆搜也是会重复的,但是怎么样判断和前面搜索过的相同呢?这里不仅和index有关,也和tmp有关,我们将tmp和index相连形成一个string,这样就生成独一无二的key了,接下来就是简单的记忆化搜索了。
class Solution {
public:
// void dfs(vector<int>& nums,int tmp, int index,int target){
// if(index == nums.size()){
// if(tmp == target) res++;
// return;
// }
// dfs(nums,tmp+nums[index],index+1,target);
// dfs(nums,tmp-nums[index],index+1,target);
// }
int dfs(vector<int>& nums,int target,int index, int tmp){
string key = to_string(index) + "_" + to_string(tmp);
if(ma.count(key)) return ma[key];
if(index == nums.size()){
ma[key] = (tmp == target?1:0);
return ma[key];
}
int left = dfs(nums,target,index+1,tmp + nums[index]);
int right = dfs(nums,target,index+1,tmp - nums[index]);
ma[key] = left + right;
return ma[key];
}
int findTargetSumWays(vector<int>& nums, int target) {
//只有+或者-
//dfs肯定超时,试试看,dfs可以过...
// dfs(nums,0,0,target);
// return res;
return dfs(nums,target,0,0);
}
private:
// int res = 0;
unordered_map<string,int> ma;
};