LeetCode 494.目标和(回溯+动态规划[类似0/1背包])

image.png

最近开始写动态规划了,题解都少写好多!!!为啥呢?太tm难了,有些题看了题解还要想个几小时。终究还是菜狗!!
image.png

不说了,继续写题解,加深理解

第一种解法:回溯

这个就不用我写了吧,感觉没有技术含量。用回溯我都感觉很愧疚,因为跟暴力差不多。但是没办法,不会就老老实实写这种了

class Solution {
    
    
    int sum=0;
    public int findTargetSumWays(int[] nums, int target) {
    
    
        int length=nums.length;
        dfs(nums,target,length,0,0,0);
        return sum;
    }

    private void dfs(int[] nums, int target, int length,int flag,int totalSum,int total) {
    
    
        if(total==length&&totalSum==target){
    
    
            sum++;
            return;
        }
        if(total<length){
    
    
        total++;
        totalSum=totalSum+nums[flag];
        dfs(nums,target,length,flag+1,totalSum,total);
        totalSum=totalSum-nums[flag];
        totalSum=totalSum-nums[flag];
        dfs(nums,target,length,flag+1,totalSum,total);
        total--;
        totalSum=totalSum+nums[flag];
        }
    }
}

第二种解法: 动态规划(在这之前需要你掌握0/1背包)

一开始就是一个难点:
先将这些数全部加起来为sum(不包含符号),我们假设选出来的数中正数和为x,那么其选出来的负数和就为sum-x(注意:这里的sum,x都是无符号的数,也就是正数)

那么题目给出的target=-(sum-x)+x(这里负数和+正数和为目标和嘛),之后给它变式一下为:x=(target+sum)/2,其中target和sum是不变的,那么你看到这里是不是明白了什么??

题目其实就变成是:我们需要从数组中找出和为x有几种组合方式(这样的话就把什么负数的给去掉了,不然搞得很麻烦一样)

如果你比较了解0/1背包的话,相信你已经有思路了,就变成了容量为x的背包有几种装法。

二维的动态规划dp[i][j]表示的含义为:从下标为0-i的数中,和为j的组合方式有dp[i][j]种
滚动数组的动态规划dp[j]表示的含义为:装满j的组合方式有dp[j]种
我们用滚动数组来做时,一定要想到二维的dp数组表示什么意思,这样就不容易搞乱

dp[0]表示容量为0的背包只有一种装法,那就是不装。故dp[0]=1

故而动态规划方程为:dp[j]=dp[j-nums[i]]+dp[j];(表示不装num[i]这个元素时的组合个数+装num[i]元素的组合个数)

class Solution {
    
    
    public int findTargetSumWays(int[] nums, int target) {
    
    
        int sum=0;
        for(int x:nums)
            sum+=x;
        if((sum+target)%2!=0||sum+target<0)
            return 0;
        int[] dp=new int[(sum+target)/2+1];
        dp[0]=1;
        for(int i=0;i<nums.length;++i){
    
    
            for(int j=(sum+target)/2;j>=nums[i];--j){
    
    
                dp[j]=dp[j-nums[i]]+dp[j];
                //System.out.print(dp[j]+" "+j+"///");
            }
            //System.out.println();
        }
        return dp[(sum+target)/2];
    }
}

image.png

猜你喜欢

转载自blog.csdn.net/small_engineer/article/details/124180238