Bootstrap

代码随想录算法训练营第三十六天 | 1049. 最后一块石头的重量 II,494. 目标和,474.一和零

第三十六天打卡,今天的题还是比较抽象,特别是后面两题,他们是01背包问题,只是递推公式变了,这点不容易想到


1049.最后一块石头的重量Ⅱ

题目链接

解题过程

  • dp[j]表示容量(这里说容量更形象,其实就是重量)为j的背包,最多可以背最大重量为dp[j]。求得dp.back()即为值最接近target的重量
  • targetsum / 2,即要求容量为target的背包中,最多装重量为多少的石头。
  • 在计算target的时候,target = sum / 2 因为是向下取整,所以sum - dp.back() 一定是大于等于dp[target]

01背包

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int sum = 0;
        int target = 0;
        for (int n : stones) sum += n;
        target = sum / 2;
        vector<int>dp(target + 1);
        for (int i = 0; i < stones.size(); i++) {
            for (int j = target; j >= 0; j--) {
                if (j >= stones[i]) {
                    dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
                }
            }
        }
        return sum - 2 * dp.back();
    }
};

494.目标和

题目链接

解题过程

  • 没想到用背包问题能解决和的方案个数问题
  • 不放物品i:即背包容量为j,里面不放物品i,装满有dp[i - 1][j]中方法。
  • 放物品i: 即:先空出物品i的容量,背包容量为(j - 物品i容量),放满背包有 dp[i - 1][j - 物品i容量] 种方法。
  • 抽象成一维dp[j] += dp[j - nums[i]]

01背包

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum = 0;
        int t = 0;
        for (int n : nums) sum += n;
        if ((target + sum) % 2 == 1) return 0;
        if (abs(target) > sum) return 0;
        t = (target + sum) / 2;
        vector<int>dp(t + 1);
        dp[0] = 1;
        for (int i = 0; i < nums.size(); i++) {
            for (int j = t; j >= nums[i]; j--) {
                dp[j] += dp[j - nums[i]];
            }
        }
        return dp.back();
    }
};

474.一和零

题目链接

解题过程

  • 还是挺难想到的,本题为01背包问题
  • dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]
  • dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);

01背包

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>>dp(m + 1, vector<int>(n + 1)); //m个0和n个1最多的子集长度
        for (string str : strs) {
            int oneNum = 0;
            int ZeroNum = 0;
            for (char c : str) {
                if (c == '0') ZeroNum++;
                else oneNum++;
            }
            for (int i = m; i >= ZeroNum; i--) {
                for (int j = n; j >= oneNum; j--) {
                    dp[i][j] = max(dp[i][j], dp[i - ZeroNum][j - oneNum] + 1);
                }
            }
        }
        return dp.back().back();
    }
};
;