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

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

链接:LeetCode1049.最后一块石头的重量
把该题抽象成01背包问题:
根据粉碎的可能结果:

  • 如果x==y,那么两块石头都会被完全粉碎
  • 如果x!=y,那么重量为x的石头将会被完全粉碎,重量为y的石头新重量为y-x.

可以得出,要想剩余的最后一块石头的重量最小,尽量每次选中的两个石头的重量相差不大,最好相等。
首先计算所有石头的重量总和
抽象成01背包问题:
背包体积为sum/2(体积偏小的一半),物品重量为stones[i],物品价值为stones[i].

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

494.目标和

链接:LeetCode494.目标和
把本题抽象成01背包问题:
所给数组nums中所有数字之和为sum
假设整数数组中负数绝对值总和为x,则sum - x -x = target。
得出x=(sum-target)/2;
抽象为01背包问题:
背包体积为x,物品重量为nums[i],物品价值为nums[i].

  1. 确定dp数组下标及含义。dp[j]表示nums中的数字组成j的方案的种数为dp[j]
  2. 确定递推公式。dp[j] += dp[j-nums[i]]
  3. 确定遍历顺序。先遍历物品后遍历背包
  4. 数组初始化。dp[0]=1;
  5. 举例推导dp数组
    需要注意的地方就是,如果abs(target)>sum那么不论怎么设置表达式都无法组成target
class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum = 0;
        for(const int&num:nums) sum+=num;
        if(abs(target)>sum) return 0;
        if((sum-target)&1) return 0;
        int bagsize = (sum-target)>>1;
        vector<int> dp(bagsize+1,0);
        dp[0]=1;
        for(int i=0;i<nums.size();++i){
            for(int j=bagsize;j>=nums[i];--j){
                dp[j]+=dp[j-nums[i]];
            }
        }
        return dp[bagsize];
    }
};

474.一和零

链接:LeetCode474一和零

  1. 确定dp数组以及下标含义。dp[i]j为“包含i个0、j个1”的最大子集长度。
  2. 确定递推公式dp[i][j] = max(dp[i][j],dp[i-zero][j-one]+1);
  3. 数组初始化。dp[0][0] = 0;
  4. 确定遍历顺序。先遍历strs后遍历背包
    5.举例推导dp数组
class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        //二维的滚动数组
        vector<vector<int>> dp(m+1,vector<int>(n+1,0));
        for(int k=0;k<strs.size();++k){
            int one = 0,zero = 0;
            for(const char&c:strs[k]) {
                if(c=='1') ++one;
                else ++zero;
            }
            for(int i=m;i>=zero;--i){
                for(int j=n;j>=one;--j){
                    dp[i][j] = max(dp[i][j],dp[i-zero][j-one]+1);
                }
            }
        }
        return dp[m][n];
    }
};

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