【动态规划】代码随想录算法训练营第四十六天 |139.单词拆分,关于多重背包,你该了解这些! ,背包问题总结篇!(待补充)

139.单词拆分

1、题目链接:. - 力扣(LeetCode)

2、文章讲解:代码随想录

3、题目:

给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:

拆分时可以重复使用字典中的单词。

你可以假设字典中没有重复的单词。

示例 1:

  • 输入: s = "leetcode", wordDict = ["leet", "code"]
  • 输出: true
  • 解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。

示例 2:

  • 输入: s = "applepenapple", wordDict = ["apple", "pen"]
  • 输出: true
  • 解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。
  • 注意你可以重复使用字典中的单词。

示例 3:

  • 输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
  • 输出: false

4、视频链接:

动态规划之完全背包,你的背包如何装满?| LeetCode:139.单词拆分_哔哩哔哩_bilibili

class Solution {public boolean wordBreak(String s, List<String> wordDict) {HashSet<String> set = new HashSet<>(wordDict);boolean[] valid = new boolean[s.length() + 1];valid[0] = true;for (int i = 1; i <= s.length(); i++) {for (int j = 0; j < i && !valid[i]; j++) {if (set.contains(s.substring(j, i)) && valid[j]) {valid[i] = true;}}}return valid[s.length()];}
}
// 另一种思路的背包算法
class Solution {public boolean wordBreak(String s, List<String> wordDict) {boolean[] dp = new boolean[s.length() + 1];dp[0] = true;for (int i = 1; i <= s.length(); i++) {for (String word : wordDict) {int len = word.length();if (i >= len && dp[i - len] && word.equals(s.substring(i - len, i))) {dp[i] = true;break;}}}return dp[s.length()];}
}

多重背包理论基础

对于多重背包,我在力扣上还没发现对应的题目,所以这里就做一下简单介绍,大家大概了解一下。

有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci ,价值是Wi 。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大。

多重背包和01背包是非常像的, 为什么和01背包像呢?

每件物品最多有Mi件可用,把Mi件摊开,其实就是一个01背包问题了。

例如:

背包最大重量为10。

物品为:

重量

价值

数量

物品0

1

15

2

物品1

3

20

3

物品2

4

30

2

问背包能背的物品最大价值是多少?

和如下情况有区别么?

重量

价值

数量

物品0

1

15

1

物品0

1

15

1

物品1

3

20

1

物品1

3

20

1

物品1

3

20

1

物品2

4

30

1

物品2

4

30

1

毫无区别,这就转成了一个01背包问题了,且每个物品只用一次。

练习题目:卡码网第56题,多重背包(opens new window)

代码如下:

// 超时了
#include<iostream>
#include<vector>
using namespace std;
int main() {int bagWeight,n;cin >> bagWeight >> n;vector<int> weight(n, 0); vector<int> value(n, 0);vector<int> nums(n, 0);for (int i = 0; i < n; i++) cin >> weight[i];for (int i = 0; i < n; i++) cin >> value[i];for (int i = 0; i < n; i++) cin >> nums[i];    for (int i = 0; i < n; i++) {while (nums[i] > 1) { // 物品数量不是一的,都展开weight.push_back(weight[i]);value.push_back(value[i]);nums[i]--;}}vector<int> dp(bagWeight + 1, 0);for(int i = 0; i < weight.size(); i++) { // 遍历物品,注意此时的物品数量不是nfor(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);}}cout << dp[bagWeight] << endl;
}

大家去提交之后,发现这个解法超时了,为什么呢,哪里耗时呢?

耗时就在 这段代码:

for (int i = 0; i < n; i++) {while (nums[i] > 1) { // 物品数量不是一的,都展开weight.push_back(weight[i]);value.push_back(value[i]);nums[i]--;}
}

如果物品数量很多的话,C++中,这种操作十分费时,主要消耗在vector的动态底层扩容上。(其实这里也可以优化,先把 所有物品数量都计算好,一起申请vector的空间。

这里也有另一种实现方式,就是把每种商品遍历的个数放在01背包里面在遍历一遍。

代码如下:(详看注释)

#include<iostream>
#include<vector>
using namespace std;
int main() {int bagWeight,n;cin >> bagWeight >> n;vector<int> weight(n, 0);vector<int> value(n, 0);vector<int> nums(n, 0);for (int i = 0; i < n; i++) cin >> weight[i];for (int i = 0; i < n; i++) cin >> value[i];for (int i = 0; i < n; i++) cin >> nums[i];vector<int> dp(bagWeight + 1, 0);for(int i = 0; i < n; i++) { // 遍历物品for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量// 以上为01背包,然后加一个遍历个数for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) { // 遍历个数dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i]);}}}cout << dp[bagWeight] << endl;
}

时间复杂度:O(m × n × k),m:物品种类个数,n背包容量,k单类物品数量

从代码里可以看出是01背包里面在加一个for循环遍历一个每种商品的数量。 和01背包还是如出一辙的。

当然还有那种二进制优化的方法,其实就是把每种物品的数量,打包成一个个独立的包。

和以上在循环遍历上有所不同,因为是分拆为各个包最后可以组成一个完整背包,具体原理我就不做过多解释了,大家了解一下就行,面试的话基本不会考完这个深度了,感兴趣可以自己深入研究一波。

#总结

多重背包在面试中基本不会出现,力扣上也没有对应的题目,大家对多重背包的掌握程度知道它是一种01背包,并能在01背包的基础上写出对应代码就可以了。

至于背包九讲里面还有混合背包,二维费用背包,分组背包等等这些,大家感兴趣可以自己去学习学习,这里也不做介绍了,面试也不会考。

背包问题汇总

年前我们已经把背包问题都讲完了,那么现在我们要对背包问题进行总结一番。

背包问题是动态规划里的非常重要的一部分,所以我把背包问题单独总结一下,等动态规划专题更新完之后,我们还会在整体总结一波动态规划。

关于这几种常见的背包,其关系如下:

通过这个图,可以很清晰分清这几种常见背包之间的关系。

在讲解背包问题的时候,我们都是按照如下五部来逐步分析,相信大家也体会到,把这五部都搞透了,算是对动规来理解深入了。

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

其实这五部里哪一步都很关键,但确定递推公式和确定遍历顺序都具有规律性和代表性,所以下面我从这两点来对背包问题做一做总结

#背包递推公式

问能否能装满背包(或者最多装多少):dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]); ,对应题目如下:

  • 动态规划:416.分割等和子集(opens new window)
  • 动态规划:1049.最后一块石头的重量 II(opens new window)

问装满背包有几种方法:dp[j] += dp[j - nums[i]] ,对应题目如下:

  • 动态规划:494.目标和(opens new window)
  • 动态规划:518. 零钱兑换 II(opens new window)
  • 动态规划:377.组合总和Ⅳ(opens new window)
  • 动态规划:70. 爬楼梯进阶版(完全背包)(opens new window)

问背包装满最大价值:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); ,对应题目如下:

  • 动态规划:474.一和零(opens new window)

问装满背包所有物品的最小个数:dp[j] = min(dp[j - coins[i]] + 1, dp[j]); ,对应题目如下:

  • 动态规划:322.零钱兑换(opens new window)
  • 动态规划:279.完全平方数(opens new window)

#遍历顺序

#01背包

在动态规划:关于01背包问题,你该了解这些!(opens new window)中我们讲解二维dp数组01背包先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。

和动态规划:关于01背包问题,你该了解这些!(滚动数组)(opens new window)中,我们讲解一维dp数组01背包只能先遍历物品再遍历背包容量,且第二层for循环是从大到小遍历。

一维dp数组的背包在遍历顺序上和二维dp数组实现的01背包其实是有很大差异的,大家需要注意!

#完全背包

说完01背包,再看看完全背包。

在动态规划:关于完全背包,你该了解这些!(opens new window)中,讲解了纯完全背包的一维dp数组实现,先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。

但是仅仅是纯完全背包的遍历顺序是这样的,题目稍有变化,两个for循环的先后顺序就不一样了。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

相关题目如下:

  • 求组合数:动态规划:518.零钱兑换II(opens new window)
  • 求排列数:动态规划:377. 组合总和 Ⅳ(opens new window)、动态规划:70. 爬楼梯进阶版(完全背包)(opens new window)

如果求最小数,那么两层for循环的先后顺序就无所谓了,相关题目如下:

  • 求最小数:动态规划:322. 零钱兑换(opens new window)、动态规划:279.完全平方数(opens new window)

对于背包问题,其实递推公式算是容易的,难是难在遍历顺序上,如果把遍历顺序搞透,才算是真正理解了

#总结

这篇背包问题总结篇是对背包问题的高度概括,讲最关键的两部:递推公式和遍历顺序,结合力扣上的题目全都抽象出来了

而且每一个点,我都给出了对应的力扣题目

最后如果你想了解多重背包,可以看这篇动态规划:关于多重背包,你该了解这些!(opens new window),力扣上还没有多重背包的题目,也不是面试考察的重点。

如果把我本篇总结出来的内容都掌握的话,可以说对背包问题理解的就很深刻了,用来对付面试中的背包问题绰绰有余!

背包问题总结:

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

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

相关文章

3分钟彻底搞懂Web UI自动化测试之【POM设计模式】

为什么要用POM设计模式 前期&#xff0c;我们学会了使用PythonSelenium编写Web UI自动化测试线性脚本 线性脚本&#xff08;以快递100网站登录举例&#xff09;&#xff1a; import time from selenium import webdriver from selenium.webdriver.common.by import By dri…

Python SSH协议库之paramiko使用详解

概要 在网络编程中,远程操作是一项非常常见的需求,特别是在服务器管理和自动化任务执行方面。Python提供了许多库来实现远程操作,其中Paramiko是一个备受欢迎的选择。Paramiko是一个纯Python编写的SSH协议库,它提供了一种简单而强大的方式来执行远程命令、上传和下载文件等…

YUNBEE云贝-热烈祝贺Guo同学成功通过Oracle 19c OCP认证考试!

恭喜Guo同学在 #Oracle19c OCP 考试中取得了OCP证书&#xff01;该认证是Oracle公司的权威技术标准&#xff0c;适用于有资格为Oracle核心产品提供服务和支持的专业人员。尽管OCP认证考题随着版本变化&#xff0c;并且是全英文考试&#xff0c;对中文习惯的人来说有一定的难度&…

怎样将PPT转成文本格式?PPT文本一键生成文本格式 工作经验分享

在日常工作和学习中&#xff0c;我们经常需要将PPT文件转换为文本格式&#xff0c;以便更好地进行编辑、搜索和分享。下面&#xff0c;我将介绍2种常见的PPT转文本格式的方法&#xff0c;帮助大家轻松实现这一需求。 方法一、使用汇帮PDF转换器软件里的“PPT文件操作”菜单进行…

我们做的小工具,爆了!

好消息&#xff0c;好消息&#xff0c;江南皮革。。 开个玩笑&#xff0c;大家好&#xff0c;我是程序员鱼皮。 前段时间我在公众号发文宣传了团队新开发的小工具《代码小抄》&#xff0c;这是一个简单易用的代码分享工具&#xff0c;可以快速、跨设备地自由分享代码。 网址&…

使用Office的小伙伴一定要把这个打开!关键时候能保命

使用电脑办公的小伙伴一定离不开Office。很多小伙伴在使用Office的时候&#xff0c;基本上都是双击打开对应的软件&#xff08;Word/Excel/Powerpoint&#xff09;就直接使用。 这种直接打开之后就使用的习惯很不值得提倡。除非你要记录的东西是一分钟就能完成的。 小白在企业上…

在四维轻云中,能够上传哪些地理空间数据?

四维轻云是一款地理空间数据在线管理平台&#xff0c;支持各类地理空间数据的在线管理、浏览及分享&#xff0c;用户可不受时间地点限制&#xff0c;随时随地上传、管理、查看及分享各类地理空间数据。平台具有项目管理、场景搭建、素材库等功能模块&#xff0c;支持在线协作管…

《JAVA与模式》之合成模式

系列文章目录 文章目录 系列文章目录前言一、合成模式二、安全式合成模式的结构三、透明式合成模式的结构四、两种实现方法的选择前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享…

有哪些知识管理软件适合中小型企业,高管必看!

在经济加速发展的今天&#xff0c;企业对信息和知识的管理需求越来越高&#xff0c;于是&#xff0c;各类知识管理软件应运而生。对于中小型企业来说&#xff0c;选择一款高效、省时、方便的知识管理软件尤其重要。下面&#xff0c;我为大家推荐三款知识管理软件&#xff0c;适…

力扣L6--- 两数之和(java版)--2024年3月12日

1.题目 2.知识点 注1&#xff1a;在Java中&#xff0c;数组的长度不是通过调用一个方法获得的&#xff0c;而是通过一个属性直接获得的。因此&#xff0c;正确的语法是nums.length而不是nums.length()。 所以应该使用int m nums.length; 注2&#xff1a;return new int[]{i,…

SpringBoot注解事务失效列举总结

Spring事务注解 Transactional失效 常规写法不会有脏数据插入。 情景一、内部调用导致事务失效 数据库中出现测试回滚的脏数据 导致该问题原因为spring执行方法数据库操作的时候会生成一个动态代理类去执行代理类的该方法&#xff0c;代理类在执行updateUser时&#xff0c;执…

2024-3-11-C++作业

1>试编程 要求&#xff1a; 提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数 源代码: #include <iostream>using namespace std;int main() {string s;cout << "请输入字符串&#xff1a;"…

CentOS 7 基于开源项目制作openssh 9.7p1二进制rpm包(内含ssh-copy-id、显示openssl版本信息)—— 筑梦之路

可参考之前的文章&#xff1a;CentOS 5/6/7 基于开源项目制作openssh 9.6p1 rpm包—— 筑梦之路_centos6 openssh9.6rpm-CSDN博客 2024年3月12日 植树节制作&#xff0c;相关文件见我的资源

力扣刷题日志-Day2 (力扣151、43、14)

151. 反转字符串中的单词 给你一个字符串 s &#xff0c;请你反转字符串中 单词 的顺序。 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开 思路&#xff1a;根据题目大意&#xff0c;空格之间的就是一个单词&#xff0c;所以我们需要利用…

swagger踩坑之请求类不显示具体字段

swagger踩坑之请求类不显示具体字段 省流&#xff1a;枚举字段需要加上ApiModelProperty注解 过程复现&#xff1a; TestEnum 枚举不加注解&#xff0c;swagger的UI类不显示详细字段 Data Accessors(chain true) ApiModel(value "test对象", description &quo…

通过Office Web Viewer站点在线展示Office文档内容

方法&#xff1a; https://view.officeapps.live.com/op/view.aspx?src经Url编码的文档线上Url地址 比如&#xff1a; //以下地址来自一份旧项目代码&#xff0c;可见用的就是该方案function OfficeFileViewOnline(url, file_type, file_name) {url "http://14.23.112.2…

算法——哈希王

242.有效的字母异位词 力扣题目链接(opens new window) 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 示例 1: 输入: s "anagram", t "nagaram" 输出: true 示例 2: 输入: s "rat", t "car&qu…

配置vscode环境极简版(C/C++)(图文)

前言 众所周知&#xff0c;vscode是一个代码编辑器&#xff0c;不能直接编译运行我们敲的代码&#xff0c;必须提前配置好环境&#xff0c;而这也是劝退一众小白的一大重要因素&#xff0c;下面我想以一种提纲挈领的方式带大家走一遍从配置环境到运行实操代码的全过程。 安装…

Java项目:基于Springboot+vue实现的付费自习室系统设计与实现(源码+数据库+毕业论文)附含微信小程序端代码

一、项目简介 本项目是一套基于Springbootvue实现的付费自习室系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观、操作简单、…

如何利用生成式人工智能完善会议纪要:捕捉会议要点的指南

在当今快节奏的商业环境中&#xff0c;有效的沟通和记录保存至关重要。有组织的会议纪要是这一过程的基石&#xff0c;它们作为会议讨论和决策的书面记录。但如何编写不仅有组织而且可以为出席者和未出席者提供可靠资源的会议纪要呢&#xff1f;让我们深入探讨一下会议纪要的艺…