首页 > 其他分享 >代码随想录day43 | 1049. 最后一块石头的重量 II 494. 目标和 474. 一和零

代码随想录day43 | 1049. 最后一块石头的重量 II 494. 目标和 474. 一和零

时间:2022-11-08 20:26:44浏览次数:72  
标签:stones target int sum 随想录 II vector 474 dp

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

题目|文章
image

思路

求剩余石头的最小重量。如果两个石头最接近总重量的平均值,那么剩余石头为最小重量。
所以先求出石头的总重量的一半。
1.数组以及下标的含义
dp[j]表示容量为j的背包,最多可以装重量为j的石头
2.确定递推公式
dp[j] = max(dp[j], dp[j - stones[i]] + stones[i])
3.数组初始化
因为石头的1 <= stones.length <= 30,1 <= stones[i] <= 1000,所以总重量的一半为15000,开始时,重量为0,将所有的值都初始化为0
4.确定遍历顺序
先遍历石头,在遍历背包。

实现

点击查看代码
class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        vector<int> dp(15001,0);
        int sum = 0;
        for(int i = 0; i < stones.size(); i++) {
            sum += stones[i];
        }   
        int target = sum/2;
        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]);
            }
        }
        return sum - dp[target] - dp[target];
    }
};

复杂度分析

  • 时间复杂度:O(n×m),n为石头的数量,m为总重量的一半。
  • 空间复杂度:O(m)

494. 目标和

题目|文章
image

思路

既然为target,那么就一定有 left组合 - right组合 = target。
left + right等于sum,而sum是固定的。
所以left = (target + sum)/2 。
target是固定的,sum是固定的,left就可以求出来。
此时问题就是在集合nums中找出和为left的组合。

实现

点击查看代码
class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum = 0;
        for(int i = 0; i < nums.size(); i++) {
            sum += nums[i];
        }
        if(abs(target) > sum) return 0;
        if((sum + target) % 2 == 1) return 0;
        int left = (sum + target) / 2;
        vector<int> dp(left + 1);
        dp[0] = 1;
        for(int i = 0; i < nums.size(); i++) {
            for(int j = left; j >= nums[i]; j--) {
                dp[j] += dp[j - nums[i]];
            }
        }
        return dp[left];
    }
};

复杂度分析

  • 时间复杂度:O(n×m),m为背包数量
  • 空间复杂度:O(m)

474. 一和零

题目|文章
image

思路

1.数组下标以及含义
dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]。
2.递推
dp[i][j] = max(dp[i][j], dp[i-num0][j-num1] + 1);
3.初始化
全部初始化为0
4.遍历顺序
为了不被覆盖,从后向前遍历

实现

点击查看代码
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 a = 0; a < strs.size(); a++) {
            vector<int> path = count(strs, a);
            int num0 = path[0];
            int num1 = path[1];
            for(int i = m; i >= num0; i--) {
                for(int j = n; j >= num1; j--) {
                    dp[i][j] = max(dp[i][j], dp[i - num0][j - num1] + 1);
                    //cout<< i << " " << j << " "<< dp[i][j] <<endl;
                }
            }
        }
        return dp[m][n];
    }
    vector<int> count(vector<string>& strs, int a) {
        vector<int> result(2,0);
        for(int i = 0; i < strs[a].size(); i++) {
            if(strs[a][i] == '0') result[0]++;
            else if(strs[a][i] == '1') result[1]++;
        }
        return result;
    } 
};

复杂度分析

  • 时间复杂度:O(n×m×s),s为数组的大小
  • 空间复杂度:O(n×m)

标签:stones,target,int,sum,随想录,II,vector,474,dp
From: https://www.cnblogs.com/suodi/p/16870982.html

相关文章