【c++】深入理解string类(3):典型OJ题 - 指南

news/2025/10/1 19:04:44/文章来源:https://www.cnblogs.com/slgkaifa/p/19122697

【c++】深入理解string类(3):典型OJ题 - 指南

一 仅仅反转字母

链接如下:https://leetcode-cn.com/problems/reverse-only-letters/submissions/

思路:

这道题目的核心就是交换,我们发现这个逻辑和当时在数据结构里学的快速排序非常类似:两个指针,一个指向开头,一个指向结尾,如果前一个指针的值小于后面指针的值,就交换。相应的在这道题目:如果前一个指针和后一个指针都是字母,那就交换。

所以我们需要先写一个判断是否是字母的函数。(c语言库中有这个函数,如果记得这个函数的名称和使用方法可以直接使用,如果不记得也可以像博主一样现写一个)。还需要写一个交换函数。注意:c++的模板中已经定义了这个函数,所以不需要我们自己实现。

代码实现如下:

class Solution {
public:
bool isLetter(char ch)  {       if(ch >= 'a' && ch <= 'z')           return true;       if(ch >= 'A' && ch <= 'Z')           return true;       return false;  }string reverseOnlyLetters(string s){size_t start=0,end=s.size()-1;while(start
  1. end = s.size() - 1 中的括号

    s.size() 是调用字符串对象ssize()成员函数,用于获取字符串的长度,括号()在这里表示调用函数,即使没有参数也必须写上
  2. s[start] 中的方括号[]

    这是 C++ 中访问字符串(或数组)元素的语法,s[start] 表示获取字符串s中索引为start的字符


二 找字符串中第一个只出现一次的字符

链接如下:https://leetcode-cn.com/problems/first-unique-character-in-a-string

思路:

我们可以用一个数组去映射26个字母出现的次数

代码实现如下:

class Solution {
public:int firstUniqChar(string s) {int count[26]={0};for(auto ch: s){count[ch-'a']++;}for(size_t i=0;i

这道题目非常的经典,很多年前就有了,许多公司现在的笔试题都还在考这道题,对于思维有一点的要求。


三 字符串里面最后一个单词的长度

链接如下:https://www.nowcoder.com/practice/8c949ea5f36f422594b306a2300315da?tpId=37&&tqId=21224&rp=5&ru=/activity/oj&qru=/ta/huawei/question-ranking

题目意思为:给你一个字符串,去找最后一个单词的长度,相当于需要你去寻找空格。这道题目是一个标准的IO型题目,不是接口型题目。

思路:

(1)寻找空格。但是如果有多个空格怎么办?例如:have a nice day。那我们就可以倒着去找空格,怎么倒着去找空格呢,string中有一个接口已经帮我们实现了:

(2)那我们在string类中怎么去实现输入和输出呢?也有接口已经帮我们实现了:

就相当于运算符重载

(3)当我们找到最后一个空格的时候,怎么计算最后一个单词的长度呢?

这里有一个小妙招:

当区间是左闭右开的时候:如[0,10),这个时候区间的长度就是所求的长度。

当区间是左闭右闭的时候:如[0,9],这个时候的区间的长度就比所求的长度少一

字符串最后一个字符的位置是size()-1  因为size指向的是最后一个字符的下一个位置假设寻找到的空格所在位置是pos

这个时候pos所指向的位置也不是我们所求区间的第一个位置,而是我们所求位置的前一个位置,所以只需要pos+1就可以了。这个时候区间为左闭右开[pos,size)

我们来尝试写一下代码:

#include
#include
using namespace std;
int main() {string str;cin >> str;size_t pos = str.rfind(' ');cout << str.size() - (pos + 1) << endl;
}

但是当我们提交之后,发现测试用例不通过,为什么呢?

注意,在C++中输入的时候,如果有多组输入,用空格或换行当作他们的间隔。(scanf也有这个问题)

那么怎么解决呢?C++帮我们想好了:

getline的作用是读取一整行,默认遇到换行才结束。

getline还有一个很厉害的功能:可以自己设定遇到哪个字符结束输入,这个符号放置在第三个参数的位置,第一个参数是istream类型,就是流插入运算符。

所以调整后的代码如下:

#include
#include
using namespace std;
int main() {string str;getline(cin,str);size_t pos=str.rfind(' ');if(pos!=str.size()){cout<< str.size()-(pos+1)<

四 字符串相加

链接如下:https://leetcode-cn.com/problems/add-strings

有些同学看到这道题的思路是:将两个字符串设置成auto类型,相加之和转化为字符串再输出,但是这样的想法是不对的。如果这个个字符串对应的数字比较小可以这样计算,但是如果这两个字符串对应的是几十亿的大数字呢,还能这样计算吗?显然不能,因为这样就越界了。

正确思路:

我们分别从最后一个数字计算相加,大于10的进位,再算前一位数字,这样循环。直到两个字符串都遍历完。

注意:这里有一个易错点:是需要两个字符串都遍历完了才行,而不是只有一个遍历完了就行。所以循环条件要用或 ||  而不是且&&(因为如果使用且的话,只要有一个遍历完了就会退出循环,这样会出错)

我们先来给出代码,再来一步一步解答:

class Solution {
public:string addStrings(string num1, string num2) {int  end1=num1.size()-1,end2=num2.size()-1;string retStr;int carry=0;while(end1>=0 || end2>=0){int val1=end1>=0?num1[end1--]-'0':0;int val2=end2>=0?num2[end2--]-'0':0;int ret=val1+val2+carry;carry=ret/10;ret=ret%10;retStr.insert(0,1,ret+'0');}if(carry){retStr.insert(0,1,'1' );}return retStr;}
};

我们一句一句解释:

int end1=num1.size()-1,end2=num2.size()-1;

这里设置了两个变量,分别指向两个字符串的最后一个字符。

int carry=0;

carry代表的英语意思是进位,将进位初始设置为0

string retStr;

设置了一个新的字符串,用来保存每次相加之和的值

while(end1>=0 ||end2 >=0)

循环条件:当两个字符串有任意一个没有遍历完都会进入循环

​
int val1 = end1 >= 0? num1[end1--] : 0;
int val2 = end2 >= 0? num2[end2--] : 0;
​

设置了两个整型变量来存储当前num1[end1] 对应的数字,end1-- 是先取值再将 end1 减 1,指向下一位);否则 val1 为 0(比如 num1 已经处理完,高位补 0)。

这里的高位补0的逻辑可能有点绕,博主再来讲解一下:

举个生活中的例子:计算 123 + 45 时,我们会自然地把它们对齐成:

这里其实就是给 45 的高位(百位)补了一个 0,变成 045 再与 123 相加。

在代码中,"高位补 0" 的逻辑体现在这里:

  • 当 end1 < 0 时(num1 已处理完所有字符),val1 取 0,相当于给 num1 的高位补 0
  • 当 end2 < 0 时(num2 已处理完所有字符),val2 取 0,相当于给 num2 的高位补 0
​int ret=val1+val2+carry;
carry = ret/10;
ret = ret%10;
​
  • int ret = val1 + val2 + carry;:当前位的两个数字加上进位,得到总和 ret
  • carry = ret / 10;:计算进位(比如 ret = 15,则 carry = 1)。
  • ret = ret % 10;:得到当前位的结果(比如 ret = 15,则当前位结果为 5)。
retStr.insert(0,1,ret+'0');

头插操作:把当前位的结果插入到 retStr的开头。

头插操作(在字符串开头插入字符)是为了保证最终结果的数字顺序正确。我们可以通过一个具体例子来理解:

而代码的计算顺序是从低位到高位(先算个位,再算十位,最后算百位):

  1. 先算个位:3 + 5 = 8 → 得到数字 "8"
  2. 再算十位:2 + 4 = 6 → 此时需要把 6 放在 8 的前面,变成 "68"
  3. 最后算百位:1 + 0 = 1 → 再把 1 放在 68 的前面,变成 "168"

这里的 "把新数字放在前面" 就是头插操作

我们在这里复习一下insert这个接口的使用

在指定位置插入多个相同字符

string& insert(size_t pos, size_t n, char c);

第一个参数是要插入的位置,第二个参数是插入字符的个数,第三个参数是需要插入的字符

其他的使用方法我们在这里暂不复习

if(carry)
{retStr.inset(0,1,'1');
}

当两个字符串都遍历结束时,可能还有进位会遗漏,这个时候就需要判断一下。如果这个时候carry不为0,那么头插一个1。

注意:这篇代码有一个易遗漏的,易错的点:为什么运算输出和输入的时候都要加上‘0’

在代码中,'0' 代表字符 '0'(ASCII 码值为 48),它的作用是将数字(整数)转换为对应的字符形式

当我们计算出某一位的结果 ret(比如 ret = 5)时,需要将这个数字存储到字符串中。但字符串只能直接存储字符,不能直接存储整数。

此时通过 '0' + ret 的运算:

  • 字符 '0' 的 ASCII 码是 48
  • 当 ret = 5 时,'0' + 5 = 48 + 5 = 53,而 53 恰好是字符 '5' 的 ASCII 码
  • 因此 '0' + ret 的结果就是数字 ret 对应的字符形式

到此,这道题我们就完成了。

但是这个代码还可不可以优化呢?


优化思路:

我们来算一下这篇代码的时间复杂度是多少?

答案是 O(N^2)

这里常犯的一个错误是很多的同学都会把这里的时间复杂度算成O(n)

原代码中使用 insert(0, ...) 头插操作,每次头插都需要将 retStr 中已有的所有字符后移一位,时间复杂度是 O(N^2)(假设结果字符串长度为 N,每次头插的时间复杂度是 O(N),共执行 N 次左右)

那么我们可不可以把时间复杂度优化成o(n)呢?

可以的。

思路:

我们将头插操作替换成尾插操作(尾插操作的时间复杂度时O(1) ),当遍历和进位都完成之后,再反转字符串就可以了。

还可以提前分配内存,避免后面频繁扩容,影响频率。原因:两个长度分别为 m 和 n 的字符串相加,结果的最大长度是 max(m, n) + 1

尾插的实现用+=:

在 C++ 的 std::string 中,+= 是用于在字符串末尾追加字符或字符串的运算符,它本质上就是一种尾插操作

+= 用于单个字符时,和 push_back() 效率相同,都是 O(1) 级别的操作(均摊时间复杂度),不会像头插那样需要移动已有字符

我们来实现代码:

class Solution {
public:string addStrings(string num1, string num2) {int  end1=num1.size()-1,end2=num2.size()-1;string retStr;int carry=0;retStr.reserve(max(num1.size(),num2.size())+1);while(end1>=0 || end2>=0){int val1=end1>=0?num1[end1--]-'0':0;int val2=end2>=0?num2[end2--]-'0':0;int ret=val1+val2+carry;carry=ret/10;ret=ret%10;retStr+=ret+'0';}if(carry){retStr+='1';}reverse(retStr.begin(),retStr.end());return retStr;}
};

注意!!!!!一定要区分reserve和reverse,一个时扩容,一个是逆置,二者不可混为一谈

倒数第二行代码逆置的时候,使用了迭代器,所以迭代器的使用其实是重要的。

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

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

相关文章

取印度孟买指数(SENSEX)实时行情API对接指南

获取印度孟买指数(SENSEX)实时行情API对接指南本文详细介绍如何通过API获取印度孟买敏感30指数(SENSEX)的实时行情数据,包含多种数据获取方式和代码示例概述 印度孟买敏感30指数(SENSEX)是印度孟买证券交易所的主要股…

网站推广存在的问题wordpress on.7主题

背景&#xff1a; 纯虚类(抽象类) 是只至少拥有一个纯虚函数的类&#xff0c;这种类可以有成员变量&#xff0c;但是不能进行单独的实例化(new&#xff0c;局部变量&#xff0c;智能指针构造等等)。其根本原因是由于纯虚类提供了未实现的成员函数&#xff0c;所以编译器无法知…

京东物流网站建设特点潜江58同城

CSS进阶 目标&#xff1a;掌握复合选择器作用和写法&#xff1b;使用background属性添加背景效果 01-复合选择器 定义&#xff1a;由两个或多个基础选择器&#xff0c;通过不同的方式组合而成。 作用&#xff1a;更准确、更高效的选择目标元素&#xff08;标签&#xff09;。…

企业建站网站认证企业的网站推广意义

目录 一、配置接口的全球单播地址 二、配置接口本地链路地址 三、配置接口任播地址 四、配置接口PMTU 配置静态PMTU&#xff1a; 配置动态PMTU&#xff1a; 五、接口配置IPV6地址示例&#xff1a; 一、配置接口的全球单播地址 全球单播地址类似于IPv4公网地址&#xff0…

网站流量推广网站1996年推广

前言 之前文章简单介绍了如何运行ginvue的前后端分离开源项目&#xff0c;该项目是学习了Gin实践教程后结合vue-element-admin写的&#xff0c;该教程讲得很详细&#xff0c;适合入门Gin。本篇文章将介绍ginvue的前后端分离开源项目中如何使用gin-jwt对API进行权限验证。 安装g…

2025青海视频号运营优质公司推荐榜:专业服务与创新策略口碑

2025氧化镁优质厂家权威推荐榜:品质卓越与技术实力深度解析 一、行业背景 氧化镁作为一种重要的无机化工产品,在众多领域都有着广泛的应用。它具有高熔点、高硬度、良好的化学稳定性等特性,被广泛应用于耐火材料、橡…

2025 年发泡陶瓷厂家 TOP 企业品牌推荐排行榜,发泡陶瓷线条 / 构件 / 装饰构件 / 空心砖 / 窗套线 / 浮雕 / 装饰线条推荐这十家公司

在建筑装饰材料行业蓬勃发展的当下,发泡陶瓷凭借其轻质、防火、耐候性强等优势,在各类建筑项目中得到广泛应用。然而,随着市场需求的不断增长,发泡陶瓷厂家数量日益增多,产品质量却参差不齐。部分厂家为追求短期利…

Future相关并发类使用

Future相关并发类使用 目录Future相关并发类使用一、Callable&Future&FutureTask 详解1. 基础组件对比:Runnable vs Callable2. Future 接口:任务管理工具3. FutureTask:Runnable 与 Future 的结合体4. Fut…

医药网站模板做网站哪家服务器好

在人工智能(AI)的浩瀚宇宙中&#xff0c;大模型以其强大的学习能力和广泛的适用性&#xff0c;正逐步成为推动技术进步和产业革新的核心动力。在这股浪潮中&#xff0c;通用大模型与垂直大模型如同两颗璀璨的星辰&#xff0c;各自散发着独特的光芒&#xff0c;共同照亮了AI发展…

东莞网站免费制作emlog to wordpress

文章目录 openssl3.2 - 测试程序的学习 - test\aesgcmtest.c概述笔记能学到的流程性内容END openssl3.2 - 测试程序的学习 - test\aesgcmtest.c 概述 openssl3.2 - 测试程序的学习 aesgcmtest.c 工程搭建时, 发现没有提供 test_get_options(), cleanup_tests(), 需要自己补上…

2025 年传感器厂家 TOP 企业品牌推荐排行榜,磁致伸缩 / 防爆 / 防水 / 隔爆 / 线性 / 矿用 / 直线 / 油缸位移传感器 / 液位传感器公司推荐!

引言当前传感器行业发展迅速,市场上品牌与产品种类繁多,给企业和采购者带来了不小的选择难题。一方面,不同品牌的传感器在技术水平、产品质量、服务能力等方面存在较大差异,部分产品难以满足工业生产中对高精度、稳…

2025 年热转印花膜厂家 TOP 企业品牌推荐排行榜,硅胶 / 五金 / 塑胶 / ABS / 涂料桶 / PP / 水杯 / 温变 / 冰变热转印花膜加工厂推荐

引言在热转印行业蓬勃发展的当下,热转印花膜作为关键材料,其市场需求日益增长。然而,行业内却存在着诸多问题,让采购者面临不少困扰。一方面,部分厂家为追求利润,在生产过程中偷工减料,导致产品质量参差不齐,有…

2025 年生物除臭设备厂家 TOP 品牌企业推荐排行榜揭晓:印染厂污水 / 食品厂污水 / 污水处理厂 / 污水泵站 / 污水站 / 餐厨垃圾 / 屠宰场 / 厨余垃圾生物除臭设备公司推荐

引言随着环保意识的不断提升,各行业对臭气治理的需求日益迫切。污水处理厂、垃圾中转站、畜牧养殖场、食品加工厂等领域,因生产经营过程中产生的恶臭气体,不仅影响周边居民生活环境,还可能对工作人员的身体健康造成…

JUC:读写锁

无锁 => 独占锁 => 读写锁 => 邮戳锁 ReentrantLock, ReentrantReadWriteLock, StampedLock 4.12.1 面试题Java有哪些锁? 对于读写锁,锁饥饿问题是什么? 有没有比读写锁更快的锁?邮戳锁 StampedLock知道码…

2025 年舞台厂家 TOP 品牌企业权威推荐榜单,铝合金舞台、活动舞台、快装舞台、舞台架、折叠舞台、演出舞台、演唱会舞台桁架、舞台设计公司推荐

引言当前舞台行业发展迅速,各类演出、展览、庆典活动对舞台设备的需求日益增长,但行业内却存在诸多问题。许多舞台厂家缺乏完整的产业链,依赖外部采购原材料和配件,不仅难以把控产品质量,还容易受供应链波动影响,…

大连网站设计九即问仟亿科技在电脑上做二建题 哪个网站好

Hi,大家好我是tom,I am back.今天要给大家讲讲linux系统一些性能相关命令。 1.fdisk 磁盘管理 是一个强大的危险命令&#xff0c;所有涉及磁盘的操作都由该命令完成&#xff0c;包括&#xff1a;新增磁盘、增删改磁盘分区等。 1.fdisk -l 查看磁盘分区情况 Disk /dev/sda: 27.8…

2025 年点胶机厂家 TOP 企业推荐排行榜,自动 / 果冻胶 / 无痕内衣 / 烫钻 / 珠宝热熔胶 / 水钻热熔胶 / 亮片热熔胶 / 金葱粉热熔胶点胶机推荐这十家公司!

引言在当前的工业生产领域,点胶机作为重要的自动化设备,其性能与质量直接影响着生产效率和产品品质。然而,市场上点胶机源头厂家数量众多,产品种类繁杂,技术水平参差不齐,让不少企业在选购时陷入困境。部分厂家缺…

2025 年知识库应用工具系统平台推荐排行榜,企业 / 行业 / 专家 / 问答 / 智能 / 培训 / 协同 / 办公 / 内部 / 外部 / 个人 / 客服 / 营销知识库应用软件推荐!

引言在当今数字化飞速发展的时代,企业面临着海量信息的管理与利用难题。知识库应用成为了解决这一困境的关键手段,它能够帮助企业整合知识资源、提升员工工作效率、促进团队协作以及为决策提供有力支持。然而,市场上…

2025 年移民服务公司性价比排行:美国、加拿大等国 TOP 机构,综合费用与服务质量的考量!

在全球化浪潮的推动下,移民已成为众多家庭寻求新发展机遇、改善生活环境、为子女提供优质教育资源的重要途径。然而,移民市场的繁荣也伴随着诸多问题。目前,市场上移民公司数量众多、鱼龙混杂,服务质量参差不齐。部…

2025 年水泥墩公司推荐最新榜单白皮书发布,圆形 / 方形 / 光伏水泥墩 / 围挡水泥墩 / 护栏水泥墩 / 交通水泥墩 / 防撞水泥墩源头厂家推荐

引言水泥墩作为基础建材,在市政基建、光伏电站等领域应用广泛,需求旺盛。但行业厂家众多,产品质量参差不齐,让采购者难以抉择。 部分厂家为利润偷工减料,导致产品强度不足、耐久性差,难抵恶劣环境;一些厂家工艺…