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

时间:2024-06-02 07:18:23

代码随想录算法训练营第四十五天

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

题目链接:1049. 最后一块石头的重量 II
将所有石头分成2组,两组的重量尽可能相等,差值最小。
计算石头总重,再除以2就是目标重量,求要达到该重量能装的石头的最大价值(重量)。

  1. 确定dp数组以及下标的含义:j为背包的最大容量,dp[j]达到j重量能装的石头的最大价值(重量)
  2. 确定递推公式:dp[j] = max(dp[j],dp[j-nums[i]]+nums[i])
  3. dp数组如何初始化:容量为0,价值(重量)为0。dp[0] = 0;
  4. 确定遍历顺序:从大到小遍历
  5. 打印dp数组。
class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int sum = 0;
        for (int& num : stones) {
            sum += num;
        }
        int target = sum / 2;
        vector<int> dp(target + 1, 0);
        dp[0] = 0;
        for (int i = 0; i < stones.size(); i++) {
            for (int j = target; j >= stones[i]; j--) {
                dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
            }
        }
        int result = sum - dp[target] - dp[target];
        return result;
    }
};

494. 目标和

题目链接:494. 目标和
将所有数字分成2组P,N,P组前面是+,N组前面是-。数组内所有元素的和sum=P+N,target=P-N。P=(sum+target)/2。问题转换为数组内满足和为P有多少种组合。

  1. 确定dp数组以及下标的含义:j为背包的最大容量,dp[j]当容量为j有几种组合方式
  2. 确定递推公式:dp[j]=dp[j]+dp[j-nums[i]],不放当前数字组成目标值的种类+必须放当前数字组成目标值的种类(为了保证一定放这个值,就要把需要的容量腾出来)
  3. dp数组如何初始化:容量为0,有一种放法,dp[0] = 1;
  4. 确定遍历顺序:从大到小遍历
  5. 打印dp数组。
class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum = 0;
        for (int& num : nums) {
            sum += num;
        }
        if ((sum + target) % 2 == 1 || sum < target)//这两种情况无解,返回0
            return 0;
        int s =(sum + target) / 2;
        if(s<0)return 0;//这种情况无解返回0
        vector<int> dp(s+1,0);
        dp[0]=1;
        for(int &num:nums){
            for(int j = s;j>=num;j--){
                dp[j]+=dp[j-num];
            }
        }
        return dp[s];
    }
};

474.一和零

题目链接:474.一和零

  1. 确定dp数组以及下标的含义:dp[i][j]表示有i个0,j个1,的背包,装满后的最大价值(每个字符串的价值为1,装满时最大字符串个数就等于最大价值)
  2. 确定递推公式:dp[i][j] = max(dp[i][j], dp[i - x_0][j - y_1] + 1);不换当前字符串的价值和换上当前字符串的价值中取较大。
  3. dp数组如何初始化:容量为0,价值为0。dp[0]=0
  4. 确定遍历顺序:从大到小遍历
  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 (auto& str : strs) {
            int x_0 = 0;
            int y_1 = 0;
            for (auto& c : str) {
                if (c == '0')
                    x_0++;
                else
                    y_1++;
            }
            for (int i = m; i >= x_0; i--) {
                for (int j = n; j >= y_1; j--) {
                    dp[i][j] = max(dp[i][j], dp[i - x_0][j - y_1] + 1);
                }
            }
        }
        return dp[m][n];
    }
};