class Solution {
int count=0;
public int findTargetSumWays(int[] nums, int target) {
dfs(nums,0,target,0);
return count;
}
void dfs(int[] nums,int index,int target,int sum){
if(index>=nums.length){
if(sum==target){
++count;
}
return;
}
dfs(nums,index+1,target,sum+nums[index]);
dfs(nums,index+1,target,sum-nums[index]);
}
}
这个回溯法时间复杂度太高了,要用动态规划。
1 但我们要消除target可能为负数的影响,所以要进行转换,将原题变为01背包问题,而不是现在的这个-11背包问题
这里实际上找的是nums[]选哪些数字可以让其和为(sum-target)/2,推导如下:
设被减去的数字和为neg,所有数字和为sum。有sum-2neg=target,则neg=(sum-target)/2
2 由于 nums[i]可以等于0 ,而且+0,-0算两种方法,所以不能让dp[i][0]都为1,可能为更大的数字
class Solution {
public int findTargetSumWays(int[] nums, int target) {
//真正的目标数字realTarget,这样才是01背包问题
int sum=0;
for(int i=0;i<nums.length;++i){
sum+=nums[i];
}
if(sum-target<0||(sum-target)%2!=0){
return 0;
}
int realTarget=(sum-target)/2;
//开始动态规划
int[][] dp=new int[nums.length+1][realTarget+1];
dp[0][0]=1;
for(int i=1;i<dp.length;++i){
for(int j=0;j<dp[0].length;++j){
if(j>=nums[i-1]){
dp[i][j]=dp[i-1][j]+dp[i-1][j-nums[i-1]];
}else{
dp[i][j]=dp[i-1][j];
}
}
}
return dp[dp.length-1][dp[0].length-1];
}
}