C++ 单词拆分

题目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背包的基础上写出对应代码就可以了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【JavaEE】线程安全与线程状态

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文于《JavaEE》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力)打造&…

Rational Arithmetic

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ☁️有理数运算 实现对两个有理数的…

机器人与3D视觉 Robotics Toolbox Python 一 安装 Robotics Toolbox Python

一 安装python 库 前置条件需要 Python > 3.6&#xff0c;使用pip 安装 pip install roboticstoolbox-python测试安装是否成功 import roboticstoolbox as rtb print(rtb.__version__)输出结果 二 Robotics Toolbox Python样例程序 加载机器人模型 加载由URDF文件定义…

Oracle SQL优化

1、书写顺序和执行顺序 在Oracle SQL中&#xff0c;查询的书写顺序和执行顺序是不同的。 1.1SQL书写顺序如下&#xff1a; SELECTFROMWHEREGROUP BYHAVINGORDER BY 1.2 SQL执行顺序 FROM&#xff1a;数据源被确定&#xff0c;表连接操作也在此步骤完成。 WHERE&#xff1a;对…

样品实验Epiclon萘系环氧树脂HP4032D说明书

样品实验Epiclon萘系环氧树脂HP4032D说明书 50克/袋

4.livox hap(大疆激光雷达)环境搭建

本文是在rk3588设备的ubuntu20.04的系统环境下搭建livox hap的。大概的步骤分为&#xff1a; 一、gcc、g、cmake 的安装 二、ros安装&#xff08;上一章已介绍&#xff09; 三、Livox SDK2的编译 四、livox_ros_driver2的编译 五、hap的点云视频录制、点播点云视频bag、ba…

Docker Swarm总结+CI/CD Devops、gitlab、sonarqube以及harbor的安装集成配置(3/5)

博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码下载地址&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb;…

网站优化SEO文章采集组合方法

为了在激烈的网络竞争中脱颖而出&#xff0c;SEO专业人士不断寻求创新的方法和技术。其中&#xff0c;SEO文章采集后重组是一项备受关注的技术&#xff0c;通过巧妙地整合和重新组织已有的信息&#xff0c;以提升网站在搜索引擎中的排名和曝光度。 SEO文章采集是这一技术的第一…

【MySQL】事务(事务四大特性+四种隔离级别+MVCC)

事务 前言正式开始事务的四大特性为什么会出现事务事务的版本支持事务提交方式事务常见操作方式启动事务回滚演示提交事务事务的异常autocommit 事务的隔离性隔离级别查看隔离级别修改隔离级别验证四种隔离级别读未提交(read uncommitted) —— 缩写为RU读提交(read committed)…

Jmeter接口自动化测试(提取CSV文件遍历数据)

CSV文件是我们参数化时一种最常用的存储数据文件格式&#xff0c;Jmeter也为我们提供了提取CSV文件数据的工具 首先在创建CSV文件之前&#xff0c;我们要保证我们的CSV文件编码格式为ANSI或者UTF-8,我们可以用记事本另存为&#xff0c;将编码改成ANSI或者UTF-8 接着打开Jmeter…

c MJPG(1)

.读取量化表&#xff0c;全局参数&#xff0c;霍夫曼表&#xff0c;恢复表编码&#xff0c;现在只是实现思路。 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sy…

CSS伪类伪元素?:hover,::before,::after使用(举例)

文章目录 什么是CSS伪类&#xff1f;什么是伪元素&#xff1f;怎么用伪元素&#xff1f;可以做些什么&#xff1f;::before&#xff0c;在标签选择器之前添加内容&#xff0c;::after正好与之相反::before&#xff0c;在类选择器之前添加内容&#xff08;:制作一个悬浮提示窗 参…

CAN总线

1、CAN总线简介 CAN总线协议&#xff08;Controller Area Network&#xff09;&#xff0c;控制器局域网总线&#xff0c;是德国BOSCH&#xff08;博世&#xff09;公司研发的一种串行通讯协议总线&#xff0c;它可以使用双绞线来传输信号&#xff0c;是世界上应用最广泛的现场…

Locust单机多核压测,以及主从节点的数据通信处理!

一、背景 这还是2个月前做的一次接口性能测试&#xff0c;关于locust脚本的单机多核运行&#xff0c;以及主从节点之间的数据通信。 先简单交代下背景&#xff0c;在APP上线之前&#xff0c;需要对登录接口进行性能测试。经过评估&#xff0c;我还是优先选择了locust来进行脚…

实现校园网开机自启动部署

❤️博客主页&#xff1a; iknow181&#x1f525;系列专栏&#xff1a; Python、JavaSE、JavaWeb、CCNP&#x1f389;欢迎大家点赞&#x1f44d;收藏⭐评论✍ 目录 一.准备工作 1、IDE安装 2、安装Selenium 1.介绍 2.下载 3、安装pywifi 1.介绍 2.下载 4、下载浏览器驱…

python 制作3d立体隐藏图

生成文件的3d图&#xff0c;例子&#xff1a; 文字&#xff1a; 隐藏图&#xff1a; 使用建议&#xff1a; &#xff11;、建议不用中文&#xff0c;因为中文太复杂&#xff0c;生成立体图效果不好。 &#xff12;、需要指定FONT_PATH&#xff0c;为一个ttf文件&#xff0c;…

NoSQL 数据建模错误会降低性能

数据建模错误是破坏性能的最简单方法之一。当您使用 NoSQL 时&#xff0c;特别容易搞砸&#xff0c;&#xff08;讽刺的是&#xff09;NoSQL 往往用于对性能最敏感的工作负载。NoSQL 数据建模最初可能看起来非常简单&#xff1a;只需对数据进行建模以适应应用程序的访问模式。但…

BatchOutput PDF for Mac(PDF 批量处理软件)

BatchOutput PDF是一款适用于 Mac 的 PDF 批量处理软件。它可以帮助用户将多个 PDF 文件进行异步处理&#xff0c;提高工作效率。 BatchOutput PDF 可以自动化执行许多任务&#xff0c;包括 PDF 文件的打印、转换、分割、压缩、加密、重命名等&#xff0c;而且它还可以将自定义…

基于python 医院预约挂号系统-计算机毕业设计源码24802

摘 要 随着互联网时代的到来&#xff0c;同时计算机网络技术高速发展&#xff0c;网络管理运用也变得越来越广泛。因此&#xff0c;建立一个基于django 医院预约挂号系统 &#xff0c;会使&#xff1b;医院预约挂号系统的管理工作系统化、规范化&#xff0c;也会提高平台形象&a…

汽美汽修店服务预约会员管理系统小程序效果如何

很多家庭中都有一辆或多辆汽车&#xff0c;无论燃油车还是新能源电车等&#xff0c;其市场中的数量及人均拥有量都很大&#xff0c;除了汽车销售业外&#xff0c;汽车美容修理店则生意也很多&#xff0c;可以看到城市中的不少街道中都有大大小小的汽车服务门店。 而在市场中&a…