494.目标和,对题解代码的深入理解

dp[0] 赋值为 1 的写法

1秒记住

class Solution {
    
    
    public int findTargetSumWays(int[] nums, int target) {
    
    
        int sum=0;
        for(int i=0; i<nums.length; i++){
    
    
            sum+=nums[i];
        }
        // 如果nums={998},target=-999
        // 显然凑不出来,所以得用target的绝对值去比较sum
        if(Math.abs(target)>sum){
    
    
            return 0;
        }
        // 因为 left 是个整数,2*left=sum+target
        // 所以 target+sum 必然是个偶数
        if((target+sum)%2 != 0){
    
    
            return 0;
        }
        int bagSize=(sum+target)/2;
        int[] dp=new int[bagSize+1];
        dp[0]=1;
        for(int i=0; i<nums.length; i++){
    
    
            for(int j=bagSize; j>=nums[i]; j--){
    
    
                dp[j]+=dp[j-nums[i]];
            }
        }
        return dp[bagSize];
    }
}

dp[0]不赋值为1的写法

思考方向是:不是背包容量为 0 时只能装 0 件物品也算一种装法,而是背包容量 j 等于 nums[i] 的时候,只能装下该物品,也就是只有一种装法。

这种思路下,我们就要考虑 0 ,因为 0 太特殊了,它可以无消耗的装 2 次,也就是 +0 和 -0,因此数组中有多少个 0 ,我们的结果就应该乘 2 的( 0 的个数)的次方

class Solution {
    
    
    public int findTargetSumWays(int[] nums, int target) {
    
    
        int sum=0;
        for(int i=0; i<nums.length; i++){
    
    
            sum+=nums[i];
        }
        // 如果nums={998},target=-999
        // 显然凑不出来,所以得用target的绝对值去比较sum
        if(Math.abs(target)>sum){
    
    
            return 0;
        }
        // 因为 left 是个整数,2*left=sum+target
        // 所以 target+sum 必然是个偶数
        if((target+sum)%2 != 0){
    
    
            return 0;
        }
        int bagSize=(sum+target)/2;
        int[] dp=new int[bagSize+1];
        // 用来记录数组中0的个数
        int num=0;
        for(int i=0; i<nums.length; i++){
    
    
            if(nums[i]==0){
    
    
                num++;
            }
            for(int j=bagSize; j>=nums[i]; j--){
    
    
                if(nums[i]!=0){
    
    
                  	// 背包容量 j 等于nums[i]的时候,
                    // 只能装下该物品,也就是只有一种装法
                    if(j==nums[i]){
    
    
                        dp[j]+=1;
                        continue;
                    }
                    // 当前要装的数字为 nums[i]
                    // 那么一共的装法就是 dp[j-nums[i]]时的装法
                    dp[j]+=dp[j-nums[i]];
                }
            }
        }
        if(Math.abs(target)==sum){
    
    
            // [1, 0] 1 这种情况,结果就是 2 的 0 的个数的次方
            // [0, 0, 0] 0 也同样的
            return 1*(int)Math.pow(2, num);
        }
				// 结果应该乘 2 的( 0 的个数)的次方
        return dp[bagSize]*(int)Math.pow(2, num);
    }
}

不把 dp[0] 赋值为 1 会多很多操作,

所以 dp[0] 就简单认为装背包容量为 0 的背包只有一种装法,因为我们需要用到这个 dp[0] 的值,所以 dp 数组长度必须取为 bagSize+1 ,不然只能像我上面那样麻烦的写了

猜你喜欢

转载自blog.csdn.net/lihuabeats/article/details/121392379