代码随想录训练营二刷第四十四天 | 01背包问题 416. 分割等和子集

代码随想录训练营二刷第四十四天 | 01背包问题 416. 分割等和子集

一、416. 分割等和子集

题目链接:https://leetcode.cn/problems/partition-equal-subset-sum/
思路:使用一维数组:定义dp[i]表示由闭区间[0,i]的物品填充背包得到的最大重量(本题视nums数组元素为重量)。
题目是划分等和子集,我们可以求出集合总数的一半作为背包容量,数组元素可以把背包容量填满,即将数组划分为两个等和子集。
确定递推公式:一维数组是重复覆盖当前数组,每次可以选择是否放入当前元素,如果不放入,即保持原来的值dp[j],放入的话就不要浪费空间,为dp[j-nums[i]]+nums[i],故dp[j] = math.max(dp[j], dp[j-nums[i]] + nums[i])。
初始化:dp[0]=0。
遍历顺序:先物品后背包,物品正序,背包逆序。
如若背包正序则会出现同一个物品重复放入,如物品1重量为1,背包空间为1时放入了,背包空间为2时又放入了。
如果先背包后物品,为了避免重复放入背包依然是逆序,背包容量固定时,每种背包容量只能放入一个物品,即为最大的物品,小的物品都放不进来或者被覆盖了。

class Solution {
    public boolean canPartition(int[] nums) {
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        if (sum % 2 != 0) return false;
        sum /= 2;
        int[] dp = new int[sum + 1];
        for (int i = 0; i < nums.length; i++) {
            for (int j = dp.length-1; j >= nums[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j-nums[i]] + nums[i]);
            }
            if(dp[sum] == sum) return true;
        }
        return dp[sum] == sum;
    }
}

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