class Solution {
int count = 0;
public int findTargetSumWays(int[] nums, int S) {
calucate(nums,0,0,S);
return count;
}
public void calucate(int[] nums,int i,int sum,int S){
if(i == nums.length){
if(sum == S){
count++;
}
}else{
calucate(nums,i+1,sum+nums[i],S);
calucate(nums,i+1,sum-nums[i],S);
}
}
}
递归的方式,每次加或者减看得到的数是否正确。
动态规划
后来前前后后又读了几遍题目,发现我上面那个表格只画了每个元素执行加法的部分,而忽略了执行减法的部分,整个表格区域应该是分为三部分:-/0/+。那么对应的表格的每一行的长度t就可以表示为:t=(sum*2)+1,其中一个sum表示nums中执行全部执行加/减能达到的数,而加的1显然是中间的0.具体表格如下图所示:
那么上面红色部分为什么得2也说的通了,因为忽略了负数部分的那个1,加上负数部分以后就可以得到正确的结果了。而绿色部分的表格值就是我们本题的解。dp表示为:dp[len - 1][sum + s]。
class Solution {
public int findTargetSumWays(int[] nums, int S) {
int sum = 0;
//求所有sum的总和,一是为了没有负数,最后求二维数组的第二位是[sum+s] 即可
for(int num :nums){
sum +=num;
}
if(Math.abs(sum) <Math.abs(S)){
return 0;
}
int t = 2*sum+1;
int[][] dp = new int[nums.length][t];
if(nums[0] == 0){
dp[0][sum] =2;
}else{
dp[0][sum+nums[0]] =1;
dp[0][sum-nums[0]] =1;
}
for(int i =1;i<nums.length;++i){
for(int j = 0;j<t;++j){
int left = (j-nums[i])>=0?j-nums[i]:0;
int right = (j+nums[i]<t)?j+nums[i]:0;
dp[i][j] =dp[i-1][left]+dp[i-1][right];
}
}
return dp[nums.length-1][sum+S];
}
}
核心在于考虑边界的问题,一定要考虑边界的问题。