Day 46 139.单词拆分

单词拆分

给定一个非空字符串 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

​ 单词视为物品,字符串视为背包,又因为可以重复使用,所以是完全背包;

​ 动规五部曲:

​ 1.确定dp数组以及下标的含义

dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词

​ 2.确定递推公式

​ 如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

​ 所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。

​ 3.dp数组如何初始化

​ 从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]一定是true,否则递推下去后面都都是false了;

​ 那么dp[0]有没有意义呢?dp[0]表示如果字符串为空的话,能否在字典中找到,很明显应该是false;

​ 但题目中说了“给定一个非空字符串 s” 所以测试数据中不会出现i为0的情况,那么dp[0]怎样定义其实无所谓了;

​ 下标非0的dp[i]初始化为false,只要没有被覆盖说明都是不可拆分为一个或多个在字典中出现的单词;

​ 其实很多时候都会出现这种dp[0]赋值和意义不一致的情况,以递推公式为主;

​ 4.确定遍历顺序

​ 讨论两层for循环的前后顺序。

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

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

​ 而本题其实求的是排列数, 拿 s = “applepenapple”, wordDict = [“apple”, “pen”] 举例;

​ “apple”, “pen” 是物品,那么我们要求 物品的组合一定是 “apple” + “pen” + “apple” 才能组成 “applepenapple”;

​ “apple” + “apple” + “pen” 或者 “pen” + “apple” + “apple” 是不可以的,此处就是强调物品之间顺序;

​ 所以一定是先遍历背包,再遍历物品

	for(int i = 1; i < s.size(); i++) {for(int j = 0; j < i; j++){string tempWord = s.substr(j, i - 1);if(dict.find(tempWord) != dict.end() && dp[j] == true){dp[i] = true;}}}

​ 5.打印dp数组:

class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> wordSet(wordDict.begin(), wordDict.end());//转化为unordered_set(即wordSet)的原因是为了提高查找效率vector<bool> dp(s.size() + 1, 0);dp[0] = true;for(int i = 1; i <= s.size(); i++) {for(int j = 0; j < i; j++){string tempWord = s.substr(j, i - j);if(wordSet.find(tempWord) != wordSet.end() && dp[j] == true){dp[i] = true;}}}return dp[s.size()];}
};

​ 时间复杂度:O(n^3),因为substr返回子串的副本是O(n)的复杂度(这里的n是substring的长度)

​ 空间复杂度:O(n)

多重背包

​ 多重背包本质上可以视为01背包,因为数量仍然是有限个;

​ 每件物品最多有M件可用,把M件摊开,其实01背包问题了;

​ 但是不能完全按照01背包的代码来写,因为vector扩容是一件非常耗时的事情;

​ 递推公式写成如下的形式,把每种商品遍历的个数放在01背包里面在遍历一遍,再递推,就解决了:

d p [ j ] = m a x ( d p [ j ] , d p [ j − k ∗ w e i g h t [ i ] ] + k ∗ v a l u e [ i ] ) dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i]) dp[j]=max(dp[j],dp[jkweight[i]]+kvalue[i])

#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单类物品数量

背包问题总结

递推公式

​ 问能否能装满背包(或者最多装多少):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.完全平方数

遍历顺序

对于01背包

​ 二维dp数组的两个for遍历的先后循序是可以颠倒的;

​ 一维dp数组的两个for循环先后循序一定是先遍历物品,再遍历背包容量

​ 对于完全背包

​ 因为dp[j] 是根据下标j之前所对应的dp[j]计算出来的;

​ 只要保证下标j之前的dp[j]都是经过计算的就可以了,颠倒是不会影响结果的;

​ 但如果题目有所变动,不再是求纯完全背包问题:

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

for循环先后循序一定是先遍历物品,再遍历背包容量

​ 对于完全背包

​ 因为dp[j] 是根据下标j之前所对应的dp[j]计算出来的;

​ 只要保证下标j之前的dp[j]都是经过计算的就可以了,颠倒是不会影响结果的;

​ 但如果题目有所变动,不再是求纯完全背包问题:

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

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

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

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

相关文章

【35分钟掌握金融风控策略26】定价策略

目录 定价策略 定价策略的开发、部署、监控和调优 定价策略开发 定价策略部署 定价策略监控 定价策略调优 定价策略 定价是对授信审批通过的客户给予合适利率的过程。如何定价、定价多少是由定价策略来决定的。定价策略的制订要遵循“收益覆盖风险”原则&#xff0c;对于…

基于Docker的JMeter分布式压测

一个JMeter实例可能无法产生足够的负载来对你的应用程序进行压力测试。如本网站所示&#xff0c;一个JMeter实例将能够控制许多其他的远程JMeter实例&#xff0c;并对你的应用程序产生更大的负载。JMeter使用Java RMI[远程方法调用]来与分布式网络中的对象进行交互。JMeter主站…

考研数学|李林《880》做不动,怎么办!?看这一篇!

在考研数学的备考过程中&#xff0c;遇到难题是很常见的情况&#xff0c;尤其是当你尝试解决李林880习题集中的问题时。他以其难度和深度著称&#xff0c;旨在帮助考生深入理解数学分析的复杂概念。 如果你在解题过程中感到困难&#xff0c;这并不是你个人的问题&#xff0c;而…

办公园区建筑科技风效果(html+threejs)

办公楼科技风(Htmlthreejs) 初始化三维场景 function init() {container document.getElementById(container);camera new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 150000000);camera.position.set(550, 600, 690);scene new THREE.Sce…

【系统运维】如何查找用户账号锁定位置

【问题】AD环境下&#xff0c;经常会遇到用户账号因输错密码次数超限而被锁的情况。 如果AD环境较简单还好说&#xff0c;但如果域控很多&#xff0c;要定位用户账号被锁在哪里就有点小麻烦了&#xff0c;比如开发人员可能会频繁登录多台服务器&#xff0c;如果某台服务器缓存了…

谷歌邮箱2024最新注册教程

大家好&#xff0c;我是蓝胖子&#xff0c;今天教大家如何注册谷歌邮箱 谷歌邮箱的注册后面的用途会经常用得到 首先&#xff0c;需要魔法自行解决 第一步&#xff1a;打开谷歌官网 www.google.com 确保谷歌官网能正常打开 第二步&#xff1a;创建账号 接下来可能会遇到这…

52岁「豹嫂」代夫尽孝送花畀奶奶被赞

歌手胡蓓蔚与「豹哥」单立文相爱28年&#xff0c;两人曾上节目分享婚姻之道&#xff0c;指婚姻最紧要有忍耐力&#xff0c;要抗拒引诱。其实除了忍耐力&#xff0c;胡蓓蔚和奶奶相处都有一套。 早前单立文带胡蓓蔚及妈妈到米芝连一星餐厅叹美食&#xff0c;庆祝奶奶89岁生日&am…

macOS Sonoma 14.5(23F79)发布

系统介绍 黑果魏叔5 月 14 日快报&#xff0c;苹果今日向 Mac 电脑用户推送了 macOS 14.5 正式版更新&#xff08;内部版本号&#xff1a;23F79 同 RC&#xff09;。这是去年 9 月发布的 macOS Sonoma 操作系统的第五次更新&#xff0c;距离上一次的 macOS Sonoma 14.4 更新已…

AcWing166. 数独-DFS剪枝与优化

题目 思路 思考问题&#xff1a;搜索顺序->考虑剪枝搜索顺序&#xff1a;先随意选择一个空格子&#xff0c;枚举该格子可填写的数字&#xff0c;当所有格子都填完的时候&#xff0c;说明可以退出了剪枝&#xff1a; 优化搜索顺序&#xff1a;随意选择一个空格子&#xff1a…

机器学习-12-sklearn案例02-集成学习

总结 参考 菜菜的sklearn课堂——随机森林 傻子都能看懂的——详解AdaBoost原理 算法使用过程 #导入数据集模块 from sklearn import datasets #分别加载iris和digits数据集 iris datasets.load_iris() #鸢尾花数据集 # print(dir(datasets)) # print(iris_dataset.keys…

76岁林子祥升级做爷爷,亲自为孙女取名

林子祥与前妻吴正元的儿子&#xff0c;现年39岁的林德信入行以来绯闻不少&#xff0c;自与圈外女友Candace拍拖后便修心养性&#xff0c;去年他已经低调与拍拖5年多Candace完婚&#xff0c;正式步入人生另一阶段。 昨日&#xff08;5月12日&#xff09;林德信借母亲节这个温馨日…

【MySQL数据库开发设计规范】之索引设计规范

欢迎点开这篇文章&#xff0c;自我介绍一下哈&#xff0c;本人姑苏老陈 &#xff0c;是一名JAVA开发老兵。 本文收录于 《MySQL数据库开发设计规范》专栏中&#xff0c;该专栏主要分享一些关于MySQL数据库开发设计相关的技术规范文章&#xff0c;定期更新&#xff0c;欢迎关注&…

【综述】人工智能、机器学习、深度学习

文章目录 前言 概念 算法 训练 性能 应用 参考资料 前言 见《初试人工智能》 概念 人工智能系统&#xff08;artifieial intelligence system&#xff09;&#xff0c;针对人类定义的给定目标&#xff0c;产生诸如内容、预测、推荐或决策等输出的一类工程系统。该工程系…

【C++】string|迭代器iterator|getline|find

目录 ​编辑 string 1.string与char* 的区别 2.string的使用 字符串遍历 利用迭代器遍历 范围for遍历 反向迭代器 字符串capacity 字符串插入操作 push_back函数 append函数 运算符 ​编辑 insert函数 substr函数 字符串查找函数 find函数 rfind函数 …

灵活的静态存储控制器 (FSMC)的介绍(STM32F4)

目录 概述 1 认识FSMC 1.1 应用介绍 1.2 FSMC的主要功能 1.2.1 FSMC用途 1.2.2 FSMC的功能 2 FSMC的框架结构 2.1 AHB 接口 2.1.1 AHB 接口的Fault 2.1.2 支持的存储器和事务 2.2 外部器件地址映射 3 地址映射 3.1 NOR/PSRAM地址映射 3.2 NAND/PC卡地址映射 概述…

GPT搜索鸽了!改升级GPT-4

最近OpenAI太反常&#xff0c;消息一会一变&#xff0c;直让人摸不着头脑。 奥特曼最新宣布&#xff1a;5月13日开发布会&#xff0c;不是GPT-5&#xff0c;也不是盛传的GPT搜索引擎&#xff0c;改成对ChatGP和GPT-4的升级&#xff5e; 消息一出&#xff0c;大伙儿都蒙了。 之…

运维别卷系列 - 云原生监控平台 之 02.prometheus exporter 实践

文章目录 [toc]exporter 简介常用的 exporternode-exporter 实践创建 svc创建 daemonsetprometheus 配置服务发现 exporter 简介 随着 Prometheus 的流行&#xff0c;很多系统都已经自带了用于 Prometheus 监控的接口&#xff0c;例如 etcd、Kubernetes、CoreDNS 等&#xff0c…

PuLID: 图像背景、光线、风格等均保持高度一致图像生成工具,附本地一键包

PuLID是一种无需调优的ID定制方法。PuLID保持了高的ID保真度&#xff0c;同时有效地减少了对原始模型行为的干扰。 只需要提供一张照片&#xff0c;就可以生成高还原度的各种风格的图像。 使用方法&#xff1a;解压一键包&#xff0c;双击一键启动 点击ID图像&#xff08;主…

Llama 3 超级课堂 -笔记

课程文档&#xff1a; https://github.com/SmartFlowAI/Llama3-Tutorial 课程视频&#xff1a;https://space.bilibili.com/3546636263360696/channel/series 1 环境配置 1.1 创建虚拟环境,名为&#xff1a;llama3 conda create -n llama3 python3.10 1.2 下载、安装 pyt…

第十六篇:数据库性能优化:从基础到高级的全面指南

数据库性能优化&#xff1a;从基础到高级的全面指南 1. 引言 在数字化的浪潮中&#xff0c;数据库作为信息系统的核心组件&#xff0c;其性能的优劣直接关系到企业的运营效率和市场竞争力。数据库性能优化不仅是一项技术挑战&#xff0c;更是一项战略任务。它要求我们深入理解…