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

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

视频讲解

主要思路:

将这堆石头分成尽可能质量相近的两堆,用01背包

代码实现:

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

算法训练营额外收获

494. 目标和

视频讲解

主要思路:

假设加法的总和为x,那么减法对应的总和就是sum - x。

所以我们要求的是 x - (sum - x) = target

x = (target + sum) / 2

此时问题就转化为,装满容量为x的背包,有几种方法。

代码实现:

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

第一次写错误 

有两种可能没有满足条件的情况:

(1)(target + sum) / 2后有余数

(2)target的绝对值比sum还大

474. 一和零

视频讲解

主要思路:

(1)dp[ i ] [ j ]:满足有i个0,j个1,且能包含最多元素的背包

(2)递推公式:本题其实仍然是01背包问题,不过无论是背包还是物品均有两个“质量”的维度,所以为了方便理解可以分开思考,先统计一个子串中0的个数,为zeroNum,然后放入背包,对背包仍用从后往前遍历,从最大m(因为最终要有m个0吗)往前遍历,则dp[ i ] = max(dp[ i ], dp[ i - zeroNum ] + 1)(+1是因为放入新的物品,即新的一个子串), 然后其实对j同理,便可以拓展到二维

(3)初始化:均初始化为0

(4)遍历顺序:与之前一样

代码实现:

class Solution {
public:
    int findMaxForm(vector& strs, int m, int n) {
        vector> dp(m + 1, vector(n + 1, 0));
        for(string str : strs) {    //遍历物品,不过这个物品质量有两个维度
            int zeroNum = 0, oneNum = 0;
            for(char character : str) { //统计物品的两个维度的质量
                if(character == '0') zeroNum++;
                if(character == '1') 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[m][n];
    }
};

你可能感兴趣的:(算法训练营,算法)