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

Day30 OK,今日份的打卡!第三十天

以下是今日份的总结

1049 最后一块石头的重量 II
494 目标和
474 一和零

今天的题目难度不低,掌握技巧了就会很简单,尽量还是写一些简洁代码 ^ _ ^

最后一块石头的重量 II

思路:

1.确定dp数组以及下标的含义
------ dp[j]表示容量(这里说容量更形象,其实就是重量)为j的背包,最多可以背最大重量为dp[j]。
2.确定递推公式
------01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
------本题 :dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
3.dp数组如何初始化
------因为重量都不会是负数,所以dp[j]都初始化为0就可以了
4.确定遍历顺序
------如果使用一维dp数组,物品遍历的for循环放在外层,遍历背包的for循环放在内层,且内层for循环倒序遍历!
5.举例推导dp数组

值得注意的是

最后dp[target]里是容量为target的背包所能背的最大重量。
在计算target的时候,target = sum / 2 因为是向下取整,所以sum - dp[target] 一定是大于等于dp[target]的。
那么相撞之后剩下的最小石头重量就是 (sum - dp[target]) - dp[target]。

//二维dp数组实现
   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];
    }

目标和

思路:
既然为target,那么就一定有
left - right = target
left + right = sum
left = (target + sum)/2 。
此时问题就转化为,装满容量为left的背包,有几种方法。

1.确定dp数组以及下标的含义
------ 填满j(包括j)这么大容积的包,有dp[j]种方法
_
2.确定递推公式
------dp[j] += dp[j - nums[i]],没弄明白什么意思,记住就可以了
_
3.dp数组如何初始化
------在初始化的时候dp[0] 一定要初始化为1
_
4.确定遍历顺序
------nums放在外循环,target在内循环,且内循环倒序
_
5.举例推导dp数组

值得注意的是

dp[j] += dp[j - nums[i]];

   int findTargetSumWays(vector<int>& nums, int target) {
        int sum = 0;
        for(int i = 0; i < nums.size();i++){
            sum += nums[i];
        }
        //没有方案
        if((target+sum)%2==1||abs(target)>sum)return 0;
        int bagSize = (target + sum)/2;
        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] + dp[j-nums[i]];//求组合类问题的公式,都是类似这种
            }
        }
        return dp[bagSize];
    }

一和零

思路:
本题中strs 数组里的元素就是物品,每个物品都是一个!
而m 和 n相当于是一个背包,两个维度的背包

1.确定dp数组以及下标的含义
------ dp[i][j]:最多有i个0和j个1的strs的最大子集的大小为dp[i][j]。
2.确定递推公式
------01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
------本题,strs里的字符串有x个0,y个1。
------所以递推公式:dp[i][j] = max(dp[i][j], dp[i - x][j - y] + 1);
------字符串的x和y相当于物品的重量(weight[i]),字符串本身的个数相当于物品的价值(value[i])
3.dp数组如何初始化
------01背包的dp数组初始化为0就可以。
------因为物品价值不会是负数,初始为0,保证递推的时候dp[i][j]不会被初始值覆盖。
4.确定遍历顺序
------一定是外层for循环遍历物品,内层for循环遍历背包容量且从后向前遍历!
5.举例推导dp数组

值得注意的是

这就是一个典型的01背包! 只不过物品的重量有了两个维度而已。

    int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0)); // 初始化全为0
        for (string str : strs) {
            int x = 0, y = 0;
            for (char a : str) {
                if (a == '0')//统计当前string的‘0’的个数
                    x++;
                if (a == '1')//统计当前string的‘1’的个数
                    y++;
            }
            for (int i = m; i >= x; i--) {
                for (int j = n; j >= y; j--) {
                    dp[i][j] = max(dp[i][j], dp[i - x][j - y] + 1);
                }
            }
        }

        return dp[m][n];
    }

写在最后

----OK,今日份的博客就写到这里,这一期的动态规划好难想,明天继续加油!!!
—还没看下期的题,但是我的栈还有一节没写;
–追不上时间进度了!!又欠了三天的(笑
-🈚️。

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-17 22:34:03       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-17 22:34:03       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-17 22:34:03       58 阅读
  4. Python语言-面向对象

    2024-07-17 22:34:03       69 阅读

热门阅读

  1. 448. 找到所有数组中消失的数字

    2024-07-17 22:34:03       20 阅读
  2. 洛谷P1255 数楼梯

    2024-07-17 22:34:03       20 阅读
  3. C#后台向某个网站发送Get或者Post请求

    2024-07-17 22:34:03       26 阅读
  4. c#中的事件

    2024-07-17 22:34:03       24 阅读
  5. 用python写一个爬虫,爬取google中关于蛇的照片

    2024-07-17 22:34:03       21 阅读
  6. Log4j的原理及应用详解(五)

    2024-07-17 22:34:03       24 阅读
  7. 私域运营 组织架构

    2024-07-17 22:34:03       20 阅读
  8. ipvsadm命令的详细使用方法

    2024-07-17 22:34:03       24 阅读
  9. 2024/6/26 Stream流

    2024-07-17 22:34:03       20 阅读
  10. 常用的设计模式有哪些

    2024-07-17 22:34:03       22 阅读
  11. 2024.07.10校招 实习 内推 面经

    2024-07-17 22:34:03       20 阅读
  12. 常用网络术语或概念

    2024-07-17 22:34:03       19 阅读