代码随想录算法训练营刷题复习1 :动态规划背包问题 01背包+完全背包

news2024/11/23 23:41:31

动态规划刷题复习

在这里插入图片描述

一、01背包

  1. 416. 分割等和子集
  2. 1049. 最后一块石头的重量 II
  3. 494. 目标和
  4. 474. 一和零

416. 分割等和子集

class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum=0;
        for(int i=0;i<nums.size();i++) {
            sum+=nums[i];
        }
        if(sum%2!=0)
            return false;
        vector<int> dp(sum/2+1,0);
        for(int i=0;i<nums.size();i++) {
            for(int j=sum/2;j>=nums[i];j--) {
                dp[j] = max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }
        if(dp[sum/2]==sum/2)
            return true;
        else
            return false;
        

    }
};

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

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        //将所有的石头分为两堆,这两队的重量尽可能地相近,最后用这两堆的重量之差的绝对值来表示最后的结果
        int sum=0;
        for(int i=0;i<stones.size();i++) {
            sum+=stones[i];
        }
        int target = sum/2;   // /是向下取整, sum-target >= target

        vector<int> dp(target+1,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]);
            }
        }
        return sum-dp[target] - dp[target];
    }
};

494. 目标和

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        //这个题,动规比较隐含,需要自己找一下这个背包容量(sum+target)/2;
        //所有元素的和为sum,x表示加法运算的和,减法背包的容量sum-x,target = x - (sum-x); 就得到了x的表达
        int sum=0;
        for(int i=0;i<nums.size();i++) 
            sum+=nums[i];
        int x = (sum+target)/2;
        vector<int> dp(x+1,0);
        //这个初始条件很重要,当初始化为全零的时候结果为0
        dp[0]=1;
        for(int i=0;i<nums.size();i++) {
            for(int j=x;j>=nums[i];j--) {
                //这里这个问总和的题,需要用+=,
                //不复习有点忘了。
                dp[j] += dp[j-nums[i]];
            }
        }
        return dp[x];
    }
};

474. 一和零

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {

        vector<vector<int>>  dp(m+1,vector<int>(n+1,0));
        //先取出来字符串数组中的每个字符串
        for(string s : strs){
            //统计这个字符串中出现了多少个0和1
            int num_0=0,num_1=0;    
            for(char c : s) {
                if(c=='0')
                    num_0++;
                else if(c=='1')
                    num_1++;
            }
            for(int i=m;i>=num_0;i--) {
                for(int j=n;j>=num_1;j--) {
                    dp[i][j] = max(dp[i][j], dp[i-num_0][j-num_1]+1);
                }
            }
        }
        return dp[m][n];
    }
};

二、完全背包问题

  1. 518 零钱兑换Ⅱ
    题目要求:符合 32 位整数范围;
  2. 377.组合总和Ⅳ
  3. 70 爬楼梯 完全背包问题版本
  4. 322.零钱兑换
  5. 279.完全平方数
    for循环中 j的界限从1开始
  6. 139.单词拆分
    这个题对unordered_set的使用以及dp[i]的更新还是不熟练

518 零钱兑换Ⅱ

class Solution {
public:
    int change(int amount, vector<int>& coins) {
        vector<int> dp(amount+1,0);
        //问组合数的问题,dp[0]初始化为1
        dp[0]=1;
        for(int i=0;i<coins.size();i++) {
            //完全背包问题,不要求仅出现一次,内层循环不用逆序
            for(int j=coins[i];j<=amount;j++) {
                //组合问题 +=
                dp[j] += dp[j-coins[i]];
            }
        }
        return dp[amount];
    }
};

377.组合总和Ⅳ

class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        //排列问题
        vector<int> dp(target+1,0);
        dp[0] = 1;
        for(int i=0;i<=target;i++) {
            for(int j=0;j<nums.size();j++) {
                //排列问题:
                //外层遍历 背包容量,内层遍历物品
                //要先判断这个背包容量和当前物品大小
                //以及满足:符合 32 位整数范围(不能超过INT_MAX)
                if(nums[j]<=i && dp[i] < INT_MAX-dp[i-nums[j]])
                    dp[i] += dp[i-nums[j]];
            }
        }
        return dp[target];
    }
};

70 爬楼梯 完全背包问题版本

class Solution {
public:
    int climbStairs(int n) {
        //把这个问题看作是完全背包问题,1和2可以无限选择
        vector<int> dp(n+1,0);
        //问总数的,dp[0]初始化为1
        dp[0]=1;
        //最少上一层台阶
        for(int i=1;i<=n;i++) {
            //这里物品遍历选择只有1,2
            for(int j=1;j<=2;j++) {
                if(i-j>=0)
                    //+=
                    dp[i] += dp[i-j];
            }
        }
        return dp[n];
    }
};

322.零钱兑换

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        //找dp[amount]最小,初始化定义为INT_MAX
        vector<int> dp(amount+1,INT_MAX);
        //dp[0]的初始化需要修改为0,
        dp[0]=0;
        //这里不用考虑组合还是排列,这个遍历顺序就是正序就行
        for(int i=0;i<coins.size();i++) {
            for(int j=coins[i];j<=amount;j++) {
                if(dp[j-coins[i]]!=INT_MAX)
                    dp[j] = min(dp[j],dp[j-coins[i]]+1);
            }
        }
        //如果凑不到这个总金额的话,这个值没有修改,就返回-1
        if(dp[amount]==INT_MAX)
            return -1;
        return dp[amount];
    }
};

279.完全平方数

class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n+1,INT_MAX);
        dp[0]=0;
        //外层遍历“背包”
        for(int i=0;i<=n;i++) {
            //内层,控制平方数不能大于i
            //j从0开始会报错:runtime error 发生溢出
            for(int j=1;j*j<=i;j++) {
                dp[i] = min(dp[i-j*j]+1,dp[i]);
            }
        }
        return dp[n];
    }
};

139.单词拆分

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        //unordered_set这个容器不熟悉

        //无序集合,值唯一,可使用find()函数来查找元素(在这里是查找单词)
        unordered_set<string> wordSet(wordDict.begin(),wordDict.end());
        vector<bool> dp(s.size()+1,false);
        dp[0]=true;
        //这里的处理逻辑:
        for(int i=1;i<=s.size();i++) {
            //这里的j实际上是从0开始找到第一个单词结束的末尾,然后把j- i-j这一段单词复制出来
            for(int j=0;j<i;j++) {
                string substr1 = s.substr(j,i-j);
                //这里这个dp[j]很关键,
                //找到上一个单词的结尾位置并且新单词也在字典中,才能为true;
                if(wordSet.find(substr1)!=wordSet.end() && dp[j])
                    dp[i] = true;
            }
        }
        return dp[s.size()];
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1827029.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Tuple 元组

文章目录 一、什么是元组 &#xff1f;二、元组的具体操作2.1 创建元组2.1.1 tuple() 创建元组函数和 list() 创建列表函数总结 2.2 元组的元素访问操作2.3 元组的元素计数操作2.4 zip 对象 一、什么是元组 &#xff1f; 列表属于可变序列,可以任意修改列表中的元素。 元组的…

JUC并发编程-第二天:线程池相关

线程池相关 线程池内置线程池的使用线程池的关闭excute方法和submit方法的区别 线程池 线程池就是一个可以复用线程的技术 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,Thread…

HTML静态网页成品作业(HTML+CSS)——游戏永劫无间网页(3个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有3个页面。 二、作品演示 三、代…

初见 Rollup 的十大常见问题

文章目录 初见 Rollup 的十大常见问题1. 超神奇的 Rollup 英文解释&#xff01;2. 为什么 ESM 要比 CommonJS 要好呢&#xff1f;3. 什么是 tree-shaking ?4. 如何使用 Rollup 处理 CommonJS&#xff1f;5. 为什么 node-resolve 不是一个内置功能&#xff1f;6. 为什么在进行代…

网络协议,OSI,简单通信,IP和mac地址

认识协议 1.讲故事 2004年&#xff0c;小明因为给他爹打电话&#xff08;座机&#xff09;费用太贵&#xff0c;所以约定一种信号&#xff0c;响一次是报平安&#xff0c;响两次是要钱&#xff0c;响三次才需要接通。 2.概念 协议&#xff1a;是一种约定&#xff0c;这种约…

如何实现电脑监视员工的电脑屏幕?六个方法偷偷分享给你

实现电脑监视员工的电脑屏幕&#xff0c;通常需要借助专业的监控软件或系统&#xff0c;这些工具旨在帮助企业管理者监督员工的工作状态&#xff0c;确保工作效率&#xff0c;同时保护公司资产和数据安全。以下是几种常见的实现方式。 1. 使用专业的远程监控软件 安企神软件&a…

kaggle竞赛实战10——特征优化

特征优化思路&#xff1a; 在完成常规流程后&#xff0c;如果不知道怎么办&#xff0c;可以针对文本or时间序列特征进行进一步处理 首先&#xff0c;我们注意到&#xff0c;每一笔信用卡的交易记录都有交易时间&#xff0c;而对于时间字段和文本字段&#xff0c;普通的批量创…

解决用Three.js实现嘴型和语音同步时只能播放部分部位的问题 Three.js同时渲染播放多个组件变形动画的方法

前言 参考这篇文章ThreeJSChatGPT 实现前端3D数字人AI互动&#xff0c;前面搭后端、训练模型组内小伙伴都没有什么问题&#xff0c;到前端的时候&#xff0c;脸部就出问题了。看我是怎么解决的。 好文章啊&#xff0c;可惜百度前几个都找不到&#xff0c;o(╥﹏╥)o 问题情况 …

【C++】环境搭建及基本工作流程

C 当你需要写性能良好的代码时&#xff0c;C仍是不二选择 如果你想访问硬件、如果你想对硬件进行控制&#xff0c;C仍是首选。 所有的游戏引擎都是用C编写的&#xff0c;因为C可以直接控制硬件。 原理&#xff1a; C代码-->编译器编译comple-->目标平台的机器码-->放…

[算法刷题—二分法]寻找插入位置

题目展示: 本道题本身并不是很难,主要是学习和分析二分查找插入位置的方法。 首先大体上分为两种情况: 一.target在待查找的数组之中,返回对应值的下标索引。 二.target不在待查找的数组之中&#xff0c;需要返回target插入位置的索引(原数组有序) 第一种情况不难&#xff…

视图-什么是(VIEW)?怎么创建(CREATE VIEW)?怎么删除(DROP)?怎么用(SELECT/INSERT/UPDATE/DELETE)?

一、引言 之前对数据库的操作都是针对基本关系表&#xff0c;操作都是在数据库的全局逻辑模式上进行的&#xff0c;而在实际的数据库系统中&#xff0c;可能用户只关心或只被允许使用数据库中的某些基本关系表或基本关系表中的某些属性列&#xff0c;这些数据构成了数据库的外…

基于SVD的点云配准(下)

点云配准及特征提取详细解读 本篇博客将介绍一个用于点云配准的 C++ 代码示例,该示例使用 PCL(Point Cloud Library)库来处理和配准两个点云数据集。我们将逐步解析代码的关键部分,并解释每个步骤的作用。 代码说明 代码的整体结构及其主要功能: int main(int argc, ch…

Vue 状态管理:从Vuex到Pinia,Vue 3官方推荐的状态管理库深度解析

大家好&#xff0c;我是前端宝哥。 在编程界有句老话&#xff1a;“命名和缓存失效是世上两大难题。” 我得说&#xff0c;在现代Web应用的状态管理上&#xff0c;这难题得排第三&#xff01; 今天&#xff0c;咱们来深挖一下Vue的状态管理之道&#xff0c;并介绍一个超直观的解…

汽车IVI中控开发入门及进阶(二十八):视频SERDES芯片

前言: SerDes不是很常见,SerDes是将Ser和Des两种产品组合在一起的名称。Ser是Serializer或“并串转换器”的缩写,Des是Deserializer或“串并转换器”的简写。 Serdes是不是必须的?上一节介绍了camera,上上节也研究了video decoder,那么带摄像头的应用应该具体选哪个方案…

从踢足球到数字孪生

前言 贵州“村超”的火热现象是一个多方面因素共同作用的结果,它不仅是一场体育赛事,更是一个文化现象,反映了时代的精神和人民的情感诉求,同时也推动了乡村振兴和地区发展。足球的魅力是多方面的,它不仅仅是一项运动,更是一种全球性的文化现象。 简单规则下的无限变化:…

MySQL数据操作与查询- select 数据查询

一、select 选择列表 1、select基本结构 select 字段列表 from 表名 where 条件表达式 说明&#xff1a; &#xff08;1&#xff09; 必须的子句只有 select 子句和 from 子句。 &#xff08;2&#xff09;where 子句用于对查询结果进行过滤。 2、选择&#xff08;查询&am…

【会议征稿,IEEE出版】第六届物联网、自动化和人工智能国际学术会议(IoTAAI 2024,7月26-28)

第六届物联网、自动化和人工智能国际会议&#xff08;IoTAAI 2024&#xff09;将于2024年07月26-28日在中国广州召开。 会议旨在拓展国际科技学术交流渠道&#xff0c;搭建学术资源共享平台&#xff0c;促进全球范围内的科技创新&#xff0c;提升中外学术合作。会议还鼓励不同领…

再谈软件设计中的抽象思维(下),从FizzBuzz到规则引擎

作为《程序员的底层思维》出版两年之后的再回顾&#xff0c;在上一篇《再谈软件设计中的抽象思维&#xff08;上&#xff09;&#xff0c;从封装变化开始》中&#xff0c;我介绍了抽象设计的本质是发现变化点&#xff0c;结合问题域&#xff0c;提炼共性&#xff0c;沉淀领域知…

Golang | Leetcode Golang题解之第151题反转字符串中的单词

题目&#xff1a; 题解&#xff1a; import ("fmt" )func reverseWords(s string) string {//1.使用双指针删除冗余的空格slowIndex, fastIndex : 0, 0b : []byte(s)//删除头部冗余空格for len(b) > 0 && fastIndex < len(b) && b[fastIndex]…

建造者模式(大话设计模式)C/C++版本

建造者模式 C 参考&#xff1a;https://www.cnblogs.com/Galesaur-wcy/p/15907863.html #include <iostream> #include <vector> #include <algorithm> #include <string> using namespace std;// Product Class&#xff0c;产品类&#xff0c;由多个…