C++ 单词拆分

news2024/11/15 7:07:31

题目1:139 单词拆分

题目链接:单词拆分

对题目的理解

字符串列表wordDict作为字典,判断是否可以利用字典中出现的单词拼接出字符串s,字典中的单词可以重复使用,题目中字符串s的长度至少为1,不存在空字符的现象

字典中的单词可以重复使用,说明是一个完全背包问题

字典wordDict中的单词就是物品,字符串s就是背包,将字符串进行划分,单词能不能填满字符串

动规五部曲

1)dp数组及下标i的含义

dp[j]:字符串的长度是j时,能否被字典中的单词组成(dp[j]=true   or     dp[j]=false)

最终判断dp[s.size()]

2)递推公式

3)dp数组初始化

dp[0]表示空字符串,字符串长度为0,题目要求字符串s的长度至少为1,所以出现空字符串没有意义,dp[0]设置为true,递推公式dp[j]的状态依赖于前面dp[i],只是为了递推公式,是基础,如果是false的话,根据递推公式1往后推,后面的都为false,

其他非零下标dp[j]设置为false,以免覆盖后面递推得到的关系

4)遍历顺序

拿 s = "applepenapple", wordDict = ["apple", "pen"] 举例。

"apple", "pen" 是物品,只有物品的组合一定是 "apple" + "pen" + "apple" 才能组成 "applepenapple"。

"apple" + "apple" + "pen" 或者 "pen" + "apple" + "apple" 是不可以的,那么强调物品之间顺序,因为字符串中每个单词的状态取决于前一个单词的状态,比如,pen取决于apple是否在字典中,如果apple在字典中,返回true,那么后面的pen在字典中找到,也返回true,如果apple未在字典中找到,即使后面的pen在字典中找到,那么pen对应的也返回false。所以,如果先遍历物品(单词)的话,即使每一个物品(单词)可以使用多次,那么由于中间夹着的其他单词还未在字典中一一对应,那么相同的单词(由数个其他单词分隔)中,后面的单词(第2个apple)也不会返回true。

所以说,本题一定是 先遍历 背包,再遍历物品(排列)。

substr的含义是substr(begin,interval)begin代表区间的起始,interval代表整个区间的长度,注意是长度,不是结尾

5)打印dp数组

代码流程及代码

代码流程(先遍历背包后遍历物品)

代码

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> wordset(wordDict.begin(),wordDict.end());
        //定义并初始化dp数组
        vector<bool> dp(s.size()+1,false);
        dp[0]=true;
        //递推,先正序遍历背包,后正序遍历物品
        for(int j=1;j<=s.size();j++){//背包,字符串s
            for(int i=0;i<j;i++){
                string word = s.substr(i,j-i);//截取i到j之间的单词
                if(wordset.find(word)!=wordset.end() && dp[i]==true) dp[j]=true;
            }
        }
        return dp[s.size()];
    }
};
  • 时间复杂度:O(n^3),因为substr返回子串的副本是O(n)的复杂度(这里的n是substring的长度)
  • 空间复杂度:O(n)

代码流程(非背包问题考虑)

不把本题考虑成背包问题的话,直接遍历字符串也是可以的,使用两个for循环,流程如下

代码

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> wordset(wordDict.begin(),wordDict.end());
        //定义并初始化dp数组
        vector<bool> dp(s.size()+1,false);
        dp[0]=true;
        //递推
        for(int i=0;i<s.size();i++){
            for(int j=i+1;j<=s.size();j++){
                string word = s.substr(i,j-i);//截取i到j之间的单词
                cout<<"j="<<j<<endl;
                cout<<"i="<<i<<endl;
                cout<<word<<endl;
                if(wordset.find(word)!=wordset.end() && dp[i]==true) dp[j]=true; 
                cout<<"dp[j=]"<<dp[j]<<endl;
            }
        }
        return dp[s.size()];
    }
};

代码流程(先遍历物品后遍历背包)这个代码放入测试用例会报错

如果是先遍历物品,再遍历背包(组合)的话,因为前面的pen还没有遍历到,所以不会被赋值成true,所以就会导致最后的一个apple不会被赋值为true

代码

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> wordset(wordDict.begin(),wordDict.end());
        //定义并初始化dp数组
        vector<bool> dp(s.size()+1,false);
        dp[0]=true;
        //递推
        for(int i=0;i<wordDict.size();i++){//物品,字符串s
            for(int j=wordDict[i].size();j<=s.size();j++){//背包
                string word = s.substr(j-wordDict[i].size(),wordDict[i].size());//截取i到j之间的单词
                if(word==wordDict[i] && dp[j-wordDict[i].size()]==true) dp[j]=true; 
            }
        }
        return dp[s.size()];
    }
};

题目2:多重背包

题目链接:多重背包

对题目的理解

N种物品,容量为V的背包,第i种物品最多有Mi件可用,每件耗费的空间是Ci,价值是Wi

求解,将哪些物品装入背包可使这些物品耗费的空间总和不超过背包容量,且价值总和最大

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

代码

#include<iostream>
#include<vector>
using namespace std;
int main(){
    int C,N;//C是容量,N是矿石的种类
    cin>>C>>N;
    vector<int> weight(N,0);
    for(int i=0;i<N;i++){
        cin>>weight[i];
    }
    vector<int> value(N,0);
    for(int i=0;i<N;i++){
        cin>>value[i];
    }
    vector<int> nums(N,0);
    for(int i=0;i<N;i++){
        cin>>nums[i];
    }
    for(int i=0;i<N;i++){
        while(nums[i]>1){//这里大于1的原因是因为前面已经放置了这种石头,所以只需要再放多余1的石头即可
            weight.push_back(weight[i]);
            value.push_back(value[i]);
            nums[i]--;
        }
    }//转化为1个01背包问题
    //定义并初始化dp数组
    vector<int> dp(C+1,0);
    //递推,先正序遍历物品,后倒序遍历背包
    for(int i=0;i<weight.size();i++){
        for(int j=C;j>=weight[i];j--){
            dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
        }
    }
    cout<<dp[C]<<endl;
}

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

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

代码

#include<iostream>
#include<vector>
using namespace std;
int main(){
    int C,N;//C是容量,N是矿石的种类
    cin>>C>>N;
    vector<int> weight(N,0);
    for(int i=0;i<N;i++){
        cin>>weight[i];
    }
    vector<int> value(N,0);
    for(int i=0;i<N;i++){
        cin>>value[i];
    }
    vector<int> nums(N,0);
    for(int i=0;i<N;i++){
        cin>>nums[i];
    }
    //定义并初始化dp数组
    vector<int> dp(C+1,0);
    //递推,先正序遍历物品,后倒序遍历背包
    for(int i=0;i<N;i++){//物品种类
        for(int j=C;j>=weight[i];j--){
            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[C]<<endl;

    
    
}

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

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

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

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

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

相关文章

YOLOv5独家原创改进: AKConv(可改变核卷积),即插即用的卷积,效果秒杀DSConv | 2023年11月最新发表

💡💡💡本文全网首发独家改进:可改变核卷积(AKConv),赋予卷积核任意数量的参数和任意采样形状,为网络开销和性能之间的权衡提供更丰富的选择,解决具有固定样本形状和正方形的卷积核不能很好地适应不断变化的目标的问题点,效果秒殺DSConv 1)AKConv替代标准卷积进行…

Attacking Fake News Detectors via Manipulating News Social Engagement(2023 WWW)

Attacking Fake News Detectors via Manipulating News Social Engagement----《通过操纵新闻社交互动来攻击假新闻检测器》 摘要 在年轻一代中&#xff0c;获取新闻的主要来源之一是社交媒体。随着新闻在各种社交媒体平台上日益流行&#xff0c;虚假信息和毫无根据的言论的传…

GPU逻辑管线

文章目录 前言一、渲染流水线二、英伟达显卡简化概念图&#xff08;GPU&#xff09;1、我们的Shader会调用英伟达提供的 API2、调用API后&#xff0c;把Shader用到的指令存储在Pushbuffer中3、然后图元分配器&#xff0c;会把 模型数据 和 Shader 指令传入GPU中4、这个SM是每个…

VGN S99快捷键,说明书

VGN S99快捷键-说明书 按键说明灯光效果常见疑难 按键说明 切换关闭电量指示灯&#xff1a;Fn home 灯光效果 常见疑难

GAN:WGAN

论文&#xff1a;https://arxiv.org/pdf/1701.07875.pdf 发表&#xff1a;2017 WGAN 算法流程 从GAN 到 WGAN 的转变 相比于原始 GAN&#xff0c;WGAN 只需要修改以下几点&#xff0c;就能使得训练更稳定&#xff0c;生成质量更高&#xff1a; 1. 此时的判别器相当于做回归…

ubuntu下QT搭建Android开发环境

一、前言 用QT开发android和直接使用android开发的区别 使用Qt开发Android应用和直接使用Android开发工具&#xff08;例如Android Studio&#xff09;有一些区别&#xff0c;主要体现在开发工具、语言、界面设计和性能等方面&#xff1a; 开发工具&#xff1a; Qt Creat…

pycharm安装django框架详细教程(指定版本)

教程目录 前言一、确保已安装好python和pycharm工具二、利用pycharm创建纯python项目&#xff0c;同时创建虚拟环境三、通过pycharm命令行安装Django指定版本四、通过pycharm命令行创建一个Django项目五、在pycharm中进行相关配置六、利用pycharm按钮启动Django项目 前言 在实…

常用API—String(操作字符串的工具类)

一&#xff0c;创建字符串的方法 二&#xff0c;案例 public static void main(String[] args) {//1,直接创建String string "gears";System.out.println(string);//2&#xff0c;用对象创建String s1 new String("xiaoheizi");System.out.println(s1);//3…

高效解决在本地打开可视化服务器端的tensorboard

文章目录 问题解决方案 问题 由于连着远程服务器构建模型&#xff0c;但是想在本地可视化却做不到&#xff0c;不要想当然天真的以为CTRLC点击链接http://localhost:6006就真能在本地打开tensorboard。你电脑都没连接服务器&#xff0c;只是pycharm连上了而已 解决方案 你需要…

有趣的代码——井字棋游戏的实现

前面我们讲解过一个猜数字游戏的实现&#xff0c;想来应该让大家感受到了属于编程的趣味性&#xff0c;并且在实现过程中应该也收获了知识。但猜数字这种简单的游戏肯定满足不了大家对于游戏的高标注、严要求&#xff0c;估计玩不了多久就会没有兴趣了&#xff0c;所以&#xf…

渗透测试-环境部署

环境部署 一、kali的环境部署二、DNSenum工具&#xff1a;深入挖掘目标域名的DNS信息三、安装Burpsuite四、安装根证书五、JSFinder的使用六、App、小程序、公众号提取 一、kali的环境部署 1.配置SSH 修改配置文件 vi /etc/ssh/sshd_config 找到 # PermitRootLogin prohibit…

收藏!7个小众宝藏的开发者学习类网站

1、simplilearn 地址&#xff1a;https://www.simplilearn.com/ simplilearn是全球排名第一的在线学习网站&#xff0c;它的课程由世界知名大学、顶级企业和领先的行业机构通过实时在线课程设计和提供&#xff0c;其中包括顶级行业从业者、广受欢迎的培训师和全球领导者。 2、…

java springboot通过application配置文件生成随机值并控制范围

我们找到 项目的 application 配置文件 这里我们还是习惯用 yml格式的 我们在配置文件中 写出 ${random.} 的时候 他就会将所有可配置的随机类型都提示出来了 有 整数 长整星 字符串 uuid 这里 我们来个模板 testcase:book:id: ${random.int}name: ${random.value}date: ${r…

[跑代码]BK-SDM: A Lightweight, Fast, and Cheap Version of Stable Diffusion

Installation(下载代码-装环境) conda create -n bk-sdm python3.8 conda activate bk-sdm git clone https://github.com/Nota-NetsPresso/BK-SDM.git cd BK-SDM pip install -r requirements.txt Note on the torch versions weve used torch 1.13.1 for MS-COCO evaluation…

了解ConcurrnetHashMap 吗?

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

kafka中的常见问题处理

文章目录 1. 如何防⽌消息丢失2. 如何防⽌重复消费3. 如何做到消息的顺序消费4. 如何解决消息积压问题4.1 消息积压问题的出现4.2 消息积压的解决⽅案 5. 实现延时队列的效果5.1 应用场景5.2 具体方案 1. 如何防⽌消息丢失 ⽣产者&#xff1a;1&#xff09;使⽤同步发送 2&…

决策树(Classification and Regression Tree)

学了数据结构的树后&#xff0c;一直没发现树有哪些应用。学而时习&#xff08;实践&#xff09;之&#xff0c;不亦说乎&#xff1f;故特地上网查了查树的应用&#xff0c;在下阐释&#xff1a; 1.文件系统&#xff1a;文件和目录的组织通常以树的形式表示&#xff0c;允许高效…

掌握Python BentoML:构建、部署和管理机器学习模型

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com BentoML是一个开源的Python框架&#xff0c;旨在简化机器学习模型的打包、部署和管理。本文将深入介绍BentoML的功能和用法&#xff0c;提供详细的示例代码和解释&#xff0c;帮助你更好地理解和应用这个强大的工…

【C++】异常处理 ③ ( 栈解旋 | 栈解旋概念 | 栈解旋作用 )

文章目录 一、栈解旋1、栈解旋引入2、栈解旋概念3、栈解旋作用 二、代码示例 - 栈解旋1、代码示例2、执行结果 一、栈解旋 1、栈解旋引入 C 程序 抛出异常后 对 局部变量的处理 : 当 C 应用程序 在 运行过程 中发生异常时 , 程序会跳转到异常处理程序 , 并执行一些操作以处理异…

10.30 作业 C++

设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 #include <iostream>using namespace std;clas…