算法修炼Day42|● 01背包问题,你该了解这些! 滚动数组 ● 416. 分割等和子集

78 阅读1分钟

01背包,完全背包和多重背包都是从01背包进化而来。所以01背包才是关键。

很明显:概念需要记下来,显然的区别是物品的个数不同。

01背包:n种物品,每种物品只有一个;

完全背包:n种物品,每种物品有无限个;

多重背包:n种物品,每种物品的个数各不相同。

动规五部曲:

dp[i][j]:[0, i] 的物品任取放入容量为j的背包(所能得到的最大价值);

LeetCode:

1.思路

求和,取模判断偶数,剪枝;

将数组作为物品,将target作为背包,判断是否存在物品之和为target的情况存在。每个物品只能用一次,因此背包采用倒序的方式。

2.代码实现
class Solution {
    public boolean canPartition(int[] nums) {
        // 求和,判偶数,剪枝
        int target = 0;
        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
        }
        if (sum % 2 != 0) {
            return false;
        }
        target = sum / 2;
        // 初始化dp[]数值
        int[] dp = new int[target + 1]; // 动态规划数组,dp[i]表示是否可以组成和为i的子集
        for (int i = 0; i < nums.length; i++) {
            for (int j = target; j >= nums[i]; j--) {
                dp[j] = Math.max(dp[j], dp[j - nums[i]] + nums[i]); // 更新dp[j]的值,表示是否可以组成和为j的子集
            }
            if (dp[target] == target) { // 如果dp[target]等于目标和,则表示可以分割成两个相等的子集
                return true;
            }
        }
        return dp[target] == target; // 返回dp[target]是否等于目标和
    }
}
3.复杂度分析

时间复杂度:O(n^2).

空间复杂度:O(n).