20200406——第四百九十四题 目标和

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];

    }
}

在这里插入图片描述

核心在于考虑边界的问题,一定要考虑边界的问题。

发布了955 篇原创文章 · 获赞 43 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_36344771/article/details/105344325