力扣416. 分割等和子集

 二维数组版本:

class Solution {
    public boolean canPartition(int[] nums){
        //数组要被分成两个,并且元素和相等,转化为背包问题:
//所有物品总重量为sum(数组元素和),现在有两个容量都为sum/2的背包,问这两个背包是否能被刚好装满,
//进一步简化:问其中一个背包能否被刚好装满(一个满了,另一个肯定也能刚好满)
        int sum = 0;
        for(int num: nums){
            sum += num;
        }

        //因为每个物品重量都是正整数,所以sum/2不为整数我们就不可能找到合适的方案。
        if(sum%2!=0)return false;

        int capacity = sum/2;//一个背包的容量

         boolean[][] dp = new boolean[nums.length][capacity+1];//dp[i][j]:一共有i件物品,每件物品重量就是nums对应的元素值,现在用一个容量为j的背包,能否将这些物品装完
         for(int j=1;j=0)//当前这件物品装得下
                    dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i]];//前者拿,后者不拿,不管拿或不拿只要能满足条件就行
                else{
                    dp[i][j] = dp[i-1][j];//装不下就只能不拿了
                }
             }
         }
         return dp[dp.length-1][dp[0].length-1];

    }
}

一维数组版本:

使用一维数组做这道题,我个人感觉就像是在参加拍卖会,比如对于力扣上的第一个例子:

nums = [1,5,11,5]

拍卖会一共有4轮,第一轮物品价值和价格(重量)都为1,第二轮物品价值和价格为5,第三轮物品价值和价格为11,第四轮物品价值和价格为5,我一共带了11元钱(sum/2也即背包容量),拍卖会每一轮我都可以选择买或不买,我的目的是把这11元钱刚好用完。

class Solution {
    public boolean canPartition(int[] nums){
        //使用一维数组外循环就是一次次去更新dp表,每次都会多一件物品要被考虑
        int sum = 0;
        for(int num: nums){
            sum += num;
        }

        //因为每个物品重量都是正整数,所以sum/2不为整数我们就不可能找到合适的方案。
        if(sum%2!=0)return false;

        int capacity = sum/2;//一个背包的容量

        boolean[] dp = new boolean[capacity+1];

        if(nums[0]=nums[i];j--){
                dp[j] = dp[j]||dp[j-nums[i]];//dp[j]:当前这轮不拿,dp[j-nums[i]]:当前这轮拿
             }
         }
         return dp[dp.length-1];

    }
}

你可能感兴趣的:(算法与数据结构,leetcode,动态规划,算法)