LeetCode刷题 Day42

90 阅读1分钟

LeetCode刷题 Day42

416. Partition Equal Subset Sum

Given a non-empty array nums containing only positive integers, find if the array can be partitioned into two subsets such that the sum of elements in both subsets is equal.

Example 1:

Input: nums = [1,5,11,5]
Output: true
Explanation: The array can be partitioned as [1, 5, 5] and [11].

Example 2:

Input: nums = [1,2,3,5]
Output: false
Explanation: The array cannot be partitioned into equal sum subsets.

思路:

  • 这是典型的背包问题, 背包的最大容量为 nums和的一半,
  1. 首先要考虑dp中j和dp[j]的意义,j为背包容量,dp[j]为当前容量下的最大和
  2. 递推公式,因为为典型的背包问题,所以就可以从是否放入背包的角度考虑
    1. 未放入背包则继续使用上一个物品的dp值,也就是dp[j]。
    2. 放入背包dp[j - num] + num。
  3. 初始化dp: 因为是sum的一半,这样 dp = Array(sum / 2 + 1).fill(0), dp[0]是0, 因为背包容量为0的时候 最大和肯定也是0
  4. 遍历顺序: 这道题的遍历顺序是一个关键,因为对于一维(滚动)数组的dp,要考虑到物品“价值"是否重复加入: 当顺序遍历背包的时候,会导致物品的重复加入,因为这是一维数组,会被之前得到的值覆盖掉。 当逆序遍历背包的时候,初始值是0, dp[n]得到值不会滚动(累计)到dp[n - 1]中。
  5. 举例论证

image.png

代码:

var canPartition = function(nums) {
    let sum = nums.reduce((a, b) => a + b);
    if (sum % 2 === 1) return false;
    sum /= 2;

    let dp = Array(sum + 1).fill(0);

    for (let num of nums) {
        for (let j = sum; j >= num; j--) {
            dp[j] = Math.max(dp[j], dp[j - num] + num);
        }
    } 
    if (dp[sum] === sum) return true;
    return false;
};

时间复杂度: O(n2), 空间复杂度: O(n)