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

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

其实背包问题画成表格可以更好的理解状态的转移。

分割等和子集

LeetCode题目:https://leetcode.cn/problems/partition-equal-subset-sum/

题目中的背包理解

  对题目进行抽象,可以看成是数组中的数值即代表重量,也代表价值。因此所求得题意即可抽象为“能否在背包容积为sum/2时候装满背包?”因此可以确定背包容积的范围最大到达sum/2即可。同时由于数组内容是无序排放,所以数组中的内容应该全部遍历,即物品应该被全部遍历。

二维背包DP思路

  按照五步进行分析,dp数组在本题目中的含义为可以取到数组中0-i个位置的数字时,容量为sum/2的背包能否装满。因此可以递推当前第i位置的j容量背包所能承载最大价值为:max(i-1位置容量背包的最大价值,i-1位置背包容量为j-第i个位置物品的容积时背包的最大价值 + 第i个位置的物品价值)。即max(dp[i-1][j],dp[i-1][j-nums[i]]+nums[i])。

  最后,根据递推公式可以执行正序的遍历。

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        for (int i = 0 ; i < nums.size() ; i++) {
            sum += nums[i];
        }
        if(sum%2==1) return false;
        vector<vector<int>> dp(nums.size(), vector(sum/2 + 1, 0));
        for (int i = 1; i < nums.size(); i++) {
            for (int j = 0; j <= sum/2; j++) {
                if (j < nums[i]) {
                    dp[i][j] = dp[i-1][j];
                }else{
                    dp[i][j] = max(dp[i-1][j], dp[i-1][j-nums[i]] + nums[i]);
                }
            }
        }
        if(dp[nums.size()-1][sum/2]==(sum/2)) return true;
        return false;
    }
};

一维滚动数组背包DP思路思路

  通过以上二维代码理解,可以看出对于当前的dp[i][j],主要依靠dp左侧的元素dp[i-1][j], dp[i-1][j-nums[i]]来决定,即只对上一行的背包容量依赖。因此可以将dp简化为对于容量为j的背包当前最大的价值,来保存当前i的数值应用在下次循环。值得注意的是,当对新的i进行迭代的时候,如果从左到右进行迭代,则会导致i-1位置的元素被覆盖,即后续无法得到正确的值。因此在i内部,背包容量应该倒序迭代。

  代码如下:

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum = 0;
        for (int i = 0 ; i < nums.size() ; i++) {
            sum += nums[i];
        }
        if(sum%2==1) return false;
        vector<int> dp(sum/2 + 1, 0);
        for (int i = 0; i < nums.size(); i++) {
            for (int j = sum/2; j >= nums[i]; j--) {
                dp[j] = max(dp[j], dp[j-nums[i]] + nums[i]);
            }
        }
        if(dp[sum/2]==(sum/2)) return true;
        return false;
    }
};

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