C++STL之string类:相关习题解析

目录

1,字符串转整型数字

2,字符串最后一个单词的长度(getline的使用)

3,仅仅反转字母

4,字符串中的第一个唯一字符(找字符串中第一个只出现一次的字符)

5,验证回文串

6,验证回文串||

7,字符串轮转

8,翻转字符串|||:翻转字符串中的单词

9,字符串中的单词反转

10,字符串相加

11,字符串相乘


1,字符串转整型数字

. - 力扣(LeetCode)

我们先来看这个:字符串 "12345" 转成整数 12345 怎么转呢?  

第一次循环时,val 初始为 0,乘以 10 还是 0,加上 '1' - '0' 即 1,val 变为 1。

第二次循环,val 为 1,乘以 10 得到 10,加上 '2' - '0' 即 2,val 变为 12,以此类推,最终得到 12345 并输出。

#include <iostream>
#include <string>
using namespace std;
int main()
{string s("12345");int val = 0;for (size_t i = 0; i < s.size(); ++i) {val *= 10;val += s[i] - '0';}cout << val << endl;return 0;
}

有了该基础,做这个题目就很轻松了

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。

函数 myAtoi(string s) 的算法如下:

  1. 读入字符串并丢弃无用的前导空格
  2. 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
  3. 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
  4. 将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
  5. 如果整数数超过 32 位有符号整数范围 [−231,  231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1
  6. 返回整数作为最终结果。

由题意得

        ① 我们先去掉前导空格,就是把前面的空格都去掉。

        ② 判断该字符串最后的正负

        ③字符串转整数 和上的转的逻辑类似,只不过多了一步需要检查溢出,因为题目说是一个 32 位有符号整数。if (val > (INT_MAX / 10) || (val == (INT_MAX / 10) && digit > 7)) :因为 INT_MAX 是 2147483647,如果当前累加的结果 val 已经大于 INT_MAX / 10 ,或者 val 等于 INT_MAX / 10 并且即将累加的数字 digit 大于 7(因为 2147483647 的十位是 4,下一位最大只能是 7),那么就会发生溢出,此时根据正负号返回 INT_MAXINT_MIN

class Solution {
public:int myAtoi(string str) {//去掉前导空格int i = 0;while(i < str.size() && str[i] == ' ') {++i;}//判断正负int flag = 1;if(i < str.size() && (str[i] == '-'|| str[i] == '+') ) {flag = (str[i] == '-') ? -1 : 1;++i;} //字符数转整数int val = 0;int digit = 0;for(; i < str.size() && isdigit(str[i]); ++i) {digit = str[i] - '0';//检查是否溢出if (val > (INT_MAX / 10) ||(val == (INT_MAX / 10) && digit > 7)) {return (flag == 1)? INT_MAX : INT_MIN;}val *= 10;val += digit;}return  val * flag;}
};

2,字符串最后一个单词的长度(getline的使用)

牛客:

字符串最后一个单词的长度_牛客题霸_牛客网

std::getline(std::cin, str) 会从标准输入(通常是键盘)读取一行文本,并将其存储到

str 字符串中。而 C++ 中的 cin 去读取的话,遇到空格或回车就会结束

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

力扣:

. - 力扣(LeetCode)

  • int end = s.size() - 1; :初始化一个索引 end ,使其指向字符串 s 的最后一个字符。

  • 接下来的 while 循环从字符串的末尾开始向前移动,跳过所有的空格字符。如果当前字符是空格,就将 end 减 1;如果遇到非空格字符,就跳出循环。

  • 如果经过上述循环后 end 变成了 -1,说明整个字符串都是空格,返回 0 。

  • int pos = s.rfind(' ', end); :使用 rfind 函数在字符串中从位置 end 往前查找第一个空格的位置,并将其索引存储在 pos 中。

  • 最后,通过 end - pos 计算出最后一个单词的长度并返回。

class Solution {
public:int lengthOfLastWord(string s) {int end = s.size() - 1;while(end >= 0) {if(s[end] == ' ') --end;elsebreak;}if(end == -1 )return 0;int pos = s.rfind(' ', end);return end - pos;}
};

3,仅仅反转字母

. - 力扣(LeetCode)

① 跳过非英文字母。并定义了一个辅助函数 isenglish, 用于判断一个字符是否为英文字母(包括小写和大写)。

② 遇到英文字母就进行交换。

class Solution {
public:bool isenglish(char c) {if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {return true;}return false;}string reverseOnlyLetters(string s) {//int start = 0;int end = s.size() - 1;while(start < end){//跳过非英文字母while(start < end && !isenglish(s[start])){++start;}while(start < end && !isenglish(s[end])){--end;}swap(s[start],s[end]);++start;--end;}return s;}
};

4,字符串中的第一个唯一字符(找字符串中第一个只出现一次的字符)

. - 力扣(LeetCode)

此题解法和计数排序的思想有点类似。

创建一个整数数组 count ,大小为 26,用于统计每个小写字母出现的次数。通过遍历字符串 s ,将每个字符 ch 对应的计数加 1, count[ch - 'a']++ 利用字符与 'a' 的差值作为索引来对应相应的字母)。

 

然后,再次遍历字符串 s ,对于每个字符,如果其在 count 数组中的计数为 1,就返回其索引 i

 

如果遍历完整个字符串都没有找到只出现一次的字符,就返回 -1。

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

5,验证回文串

. - 力扣(LeetCode)

① 如果是空串就是回文。

② 跳过非字母字符以及数字

③ 都转成小写进行比较

class Solution {
public:bool iselglishchar(char ch) {if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')) {return true;}return false;}bool isPalindrome(string s) {if(s == " " ) {return true;}int start = 0;int end = s.size() - 1;while(start < end) {//跳过非字母字符while(start < end && !iselglishchar(s[start])){++start;} while(start < end && !iselglishchar(s[end])) {--end;}if(tolower(s[start]) !=  tolower(s[end])) {return false;}++start;--end;}return true;}
};

6,验证回文串||

. - 力扣(LeetCode)

以 "abdda" 这个串为例,此时 i 指向'b',j 指向'd',发现不对了。

但是有一次删除的机会,我们自己写几个情况其实就能发现,此时子串范围为(i+1, j)

或 (i, j-1) 的两个子串只要有任意一个是回文串,则结果就是回文串,否则就不是。

当 "ab" 我们随便删除一个都是 true,所以"ab" 删除之后,返回的是 true。

class Solution {
public:bool isVild(string s, int start, int end) {while(start < end) {if(s[start] != s[end]){return false;}++start;--end;}return true;}bool validPalindrome(string s) {int start = 0;int end = s.size() - 1;while(start < end) {if(s[start] != s[end]) {return  isVild(s,start+1, end) || isVild(s,start,end-1);// (s,1,1)       // (s.0,0)}++start;--end;}return true;}
};

7,字符串轮转

. - 力扣(LeetCode)

① s1.size() == s2.size() :首先检查两个字符串的长度是否相等。如果长度不相等,那么它们肯定不是翻转关系,直接返回 false

② (s2 + s2).find(s1)!= string::npos :如果长度相等,那么将 s2 自身连接起来得到 s2 + s2 。然后在这个新字符串中查找 s1 。如果能找到(即 find 函数的返回值不为 string::npos ,表示未找到的特殊值),说明 s1 可以通过某种方式在 s2 的翻转中得到,返回 true ;如果找不到,返回 false

class Solution {
public:bool isFlipedString(string s1, string s2) {return s1.size() == s2.size() && (s2 + s2).find(s1) != string::npos;}
};

8,翻转字符串|||:翻转字符串中的单词

. - 力扣(LeetCode)

① 函数 _reverseWords 用于反转指定范围内的字符顺序。通过一个循环,不断交换起始位置 start 和结束位置 end 的字符,实现反转。

 

② 函数 reverseWords 首先定义一个起始位置 start ,然后遍历输入字符串 s 。当遇到空格时,调用 _reverseWords 函数反转从 start 到当前空格前一位(即 i - 1 )的单词。然后更新 start 为空格后的位置(即 i + 1 )。

 

③ 遍历结束后,再单独处理最后一个单词,因为它后面没有空格来触发反转。

 

④ 最终返回反转单词顺序后的字符串 s

 

比如说,对于输入字符串 "hello world" ,首先会反转 "hello""olleh" ,然后更新 start ,接着反转 "world""dlrow" ,得到最终结果 "olleh dlrow"

class Solution {
public:// 反转单词void _reverseWords(string& s, int start, int end) {while (start < end) {char tmp = s[start];s[start++] = s[end];s[end--] = tmp;}}string reverseWords(string s) {int start = 0;for (size_t i = 0; i < s.size(); ++i) {if (s[i] ==' ') {_reverseWords(s, start, i - 1);start = i + 1;}}// 处理最后一个单词_reverseWords(s, start, s.size() - 1);return s;}
};

9,字符串中的单词反转

移除元素:

. - 力扣(LeetCode)

① 定义一个慢指针和一个快指针

② fast 指向我们想要获取的元素。

③ slow 指向获取快指针获取的元素所指向新的位置 ;

④ 当快指针指向了需移除的元素时,快指针跳过他,因为这个元素不是我们需要的,到达下一个位置,下一个位置不是要移除的元素就是,我们需要的元素,所需元素就复制给 slow 指针。

class Solution {
public:int removeElement(vector<int>& nums, int val) {int slow = 0;for(int fast = 0; fast < nums.size(); ++fast) {if(nums[fast] != val) {nums[slow] = nums[fast];++slow;}}return slow;}
};

单词反转:

. - 力扣(LeetCode)

该题目的关键就是处理空格。也是我们第一步需要做的事情。

这个题目和轮转数组类似,只不过多了一步,需要处理多余的空格。

① 处理空格

        处理空格的思路就和上面的移除元素类似的,我们假设单词间隔只是一个空格,就更好理解了,如下图所示:

       我们处理完空格之后,也就意味着长度要变小,所以用 resize 来调整字符串的长度。

② 每个单词反转

③ 整体单词反转

class Solution {
public:string reverseMessage(string message) {//1,处理空格int slow = 0;for(int fast = 0; fast < message.size(); ++fast) {if(message[fast] != ' ') {if(slow != 0) {message[slow++] = ' '; //就算存在很多空格也会被覆盖}while(fast < message.size() && message[fast] != ' '){message[slow++] = message[fast++];}}}message.resize(slow);//2,单词反转int pos = 0;for(int i = 0; i < message.size(); ++i) {if(message[i] == ' ') {if(pos < i)reverse(message.begin() + pos, message.begin() + i);pos = i + 1;}}//最后一个单词反转if(pos < message.size()) {reverse(message.begin() + pos, message.end());}//整体翻转reverse(message.begin(), message.end());return  message;}
};

10,字符串相加

. - 力扣(LeetCode)

  • 初始化:

    • 定义两个指针 ij 分别指向两个字符串 num1num2 的末尾。
    • 初始化进位 cur 为 0 。
    • 创建一个空字符串 result 用于存储相加的结果。
  • 进入循环,只要以下三个条件之一满足就继续循环:

    • i 大于等于 0,即 num1 还有未处理的数字。
    • j 大于等于 0,即 num2 还有未处理的数字。
    • 进位 cur 大于 0,表示进位了(因为最后加完) 。
  • 在循环内部:

    • 如果 i 大于等于 0 ,获取 num1 对应位置的数字并减去字符 '0' 的值,得到实际数字 sum1 ,如果 i 小于 0 ,则 sum1 为 0 。
    • 同样,如果 j 大于等于 0 ,获取 num2 对应位置的数字并减去字符 '0' 的值,得到实际数字 sum2 ,如果 j 小于 0 ,则 sum2 为 0 。
  • 计算当前位的总和 sumsum1 + sum2 + cur

  • 将总和对 10 取余,加上字符 '0' 的值,添加到结果字符串 result 中。

  • 更新进位 cur 为总和除以 10 的值。

  • 如果 i 大于等于 0 ,将 i 减 1 ;如果 j 大于等于 0 ,将 j 减 1 。

  • 循环结束后,反转结果字符串 result

  • 返回最终的结果字符串。

class Solution {
public:string addStrings(string num1, string num2) {//倒着加,记录进位,保存数组到字符串,翻转字符串int i = num1.size() - 1;int j = num2.size() - 1;int cur = 0;string result = "";while(i >= 0 || j >= 0 || cur > 0) {int sum1 = (i >= 0) ? (num1[i] - '0') : 0;int sum2 = (j >= 0) ? (num2[j] - '0') : 0;int sum = sum1 + sum2 + cur;result += sum % 10 + '0';  //两个数相加的结果cur = sum / 10;  //看看是否进位 1,没有就是 0if(i >= 0)--i;if(j >= 0) --j;}reverse(result.begin(),result.end()); //反转return result;}
};

11,字符串相乘

. - 力扣(LeetCode)

  • 首先,计算两个输入字符串 num1num2 的长度,并进行特殊情况判断。如果其中一个字符串表示的数字为 0(即长度为 1 且字符为 '0'),则直接返回 "0" 。

  • num1 分配一个整数数组 nums1 ,并将 num1 中的字符转换为对应的整数。

  • 初始化一个整数数组 sums 用于存储乘法运算的中间结果和最终求和结果,初始值都为 0 。

  • 进行乘法运算和累加:

    • 对于 num2 中的每个数字(从右往左),取出当前数字 multiply1
    • 对于 num1 中的每个数字(从右往左),计算 multiply1 与当前数字的乘积,并累加到 sums 数组中对应的位置(位置由两个数字的位置决定)。
  • sums 数组进行求和处理:

    • 如果某个位置的数字大于等于 10,将其除以 10 的商累加到下一位,当前位取余数。
  • sums 数组中的数字转换为字符并连接成字符串 sb 。如果最后一位是 0 且是唯一的非零数字,则跳过不添加。

  • 反转字符串 sb

  • 释放为 nums1sums 分配的内存。

  • 返回最终的结果字符串 sb

 

class Solution {
public:string multiply(string num1, string num2) {//1,计算字符串的长度int len1 = num1.size();int len2 = num2.size();//其中一个为 0if(len1 == 1 && num1[0] - '0' == 0 || len2 == 1 && num2[0] - '0' ==0) {return "0";}//第一个数转整数int* nums1 = new int[len1];for(int i = 0; i < len1; ++i) {num1[i] = (num1[i] - '0');}//累加int* sums = new int[len1 + len2]();for(int i = 0; i < len2; ++i) {int multiply1 = num2[len2 - 1 -i] - '0';for(int j = 0; j < len1; ++j) {sums[i + j] += multiply1 * num1[len1 - 1 - j]; //第一波相对于一行,三行相加}}//求和 string sb = "";for(int i = 0; i < len1 + len2; ++i) {if(sums[i] >= 10) {sums[i + 1] += sums[i] / 10; //后一位加上前面的进位 +=sums[i] = sums[i] % 10;  // 第一位直接取余赋值}if(i == len1 + len2 -1 && sums[i] == 0)   //跳过最后,如果值为 0 防止把 '0' 赋值到字符串前面continue;sb += sums[i] + '0';}reverse(sb.begin(),sb.end());delete[] nums1;delete[] sums;return sb;}
};

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

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

相关文章

Vue 3 + 天地图 + D3.js 绘制行政区划

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;组件封装篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来组件封装篇专栏内容:组件封装-天地图 目录 引入天地图 API 初始化地图 引入 D3.js 加载行政区划数据 添…

mysql聚合函数和分组

我最近开了几个专栏&#xff0c;诚信互三&#xff01; > |||《算法专栏》&#xff1a;&#xff1a;刷题教程来自网站《代码随想录》。||| > |||《C专栏》&#xff1a;&#xff1a;记录我学习C的经历&#xff0c;看完你一定会有收获。||| > |||《Linux专栏》&#xff1…

小五金加工:细节决定产品质量与性能

在小五金加工领域&#xff0c;细节往往决定着最终产品的质量、性能以及市场竞争力。看似微不足道的细微之处&#xff0c;实际上蕴含着巨大的影响。时利和将介绍小五金加工中细节的重要性。 首先&#xff0c;细节关乎产品的精度。小五金零件通常尺寸较小&#xff0c;但对精度的要…

TorchChat:Ollama的潜在对手

PyTorch最近发布TorchChat&#xff0c;TorchChat允许在本地台式机、笔记本电脑或移动设备上下载和运行大型语言模型。会不会让你想到什么&#xff0c;没错就是Ollama。TorchChat是一个适应性强的框架&#xff0c;旨在提高各种硬件平台的LLMs效率&#xff0c;有助于在各种设备上…

怎样使用sudo的时候不需要输入密码?

在Ubuntu等Linux系统下&#xff0c;经常要在个人账户使用sudo命令来执行一些需要root权限的命令&#xff0c;但是需要输入该账户的密码&#xff0c;有时候显得很繁琐&#xff0c; 那么怎样使用sudo的时候不需要输入密码呢&#xff1f; 有如下两种方法&#xff1a; 常规方法1…

解决 Swift 6 全局变量不能满足并发安全(concurrency-safe)读写的问题

概述 WWDC 24 终于在 Swift 十岁生日发布了全新的 Swift 6。这不仅意味着 Swift 进入了全新的“大”版本时代&#xff0c;而且 Swift 编译器终于做到了并发代码执行的“绝对安全”。 不过&#xff0c;从 Swift 5 一步迈入“新时代”的小伙伴们可能对新的并发检查有些许“水土不…

迭代器失效

一、什么是迭代器失效 迭代器的主要作用就是让算法能够不用关心底层数据结构&#xff0c;其底层实际就是一个指针&#xff0c;或者是对指针进行了封装&#xff0c;比如&#xff1a;vector的迭代器就是原生态指针T* 。因此迭代器失效&#xff0c;实际就是迭代器底层对应指针所指…

使用Virtio Driver实现一个计算阶乘的小程序——QEMU平台

目录 一、概述 二、代码部分 1、Virtio 前端 (1) User Space (2) Kernel Space 2、Virtio 后端 三、运行 QEMU Version&#xff1a;qemu-7.2.0 Linux Version&#xff1a;linux-5.4.239 一、概述 本篇文章的主要内容是使用Virtio前后端数据传输的机制实现一个计算阶乘的…

【RabbitMQ】 相关概念 + 工作模式

本文将介绍一些MQ中常见的概念&#xff0c;同时也会简单实现一下RabbitMQ的工作流程。 MQ概念 Message Queue消息队列。是用来存储消息的队列&#xff0c;多用于分布式系统之间的通信。 系统间调用通常有&#xff1a;同步通信和异步通信。MQ就是在异步通信的时候使用的。 同…

萝卜快跑和端到端的自动驾驶(1)

先看一篇论文 2311.18636 (arxiv.org) 这篇论文里有一个非常好的图 比较了一下模块化任务(级联任务)和端到端自动驾驶的区别 首先什么叫模块化任务(级联) 如上图所示&#xff0c;左边的方块中的子方块&#xff0c;是展示了自动驾驶获取数据的途径&#xff0c;这里包括&…

Java之文件操作和IO

目录 File类 属性 构造方法 方法 文件内容的读写 InputStream OutputStream File类 属性 修饰符及类型属性说明static StringpathSeparator依赖于系统的路径分隔符&#xff0c;String类型的表示static charpathSeparator依赖于系统的路径分隔符&#xff0c;char类型的…

vscode 远程免密登录

Windows R 输入 cmd在命令行终端中输入 ssh-keygen 一直回车、确定 生成秘钥 3. C:\用户\xxx.ssh 拷贝公钥内容 id_rsa.pub 4. 在虚拟机~/.ssh/ 下创建文件touch authorized_keys,拷贝公钥内容 id_rsa.pub粘贴到authorized_keys里即可。

uniapp自定义请求头信息header

添加请求头&#xff1a;uniapp自定义请求头信息header&#xff0c;如下&#xff1a;添加tenant-id参数 代码

信创教育:培养未来科技创新的生力军

随着全球数字化转型的加速&#xff0c;信息技术应用创新&#xff08;简称“信创”&#xff09;产业作为推动国家信息技术自主可控和产业升级的关键领域&#xff0c;正迎来前所未有的发展机遇。信创教育&#xff0c;作为培养未来科技创新生力军的重要阵地&#xff0c;其重要性和…

win的netassist TCP测试工具和Linux的nc工具使用

写在前面 有时工作中我们编写一些tcp相关的程序&#xff0c;而netassist就是这样一款辅助我们进行TCP功能测试的工具&#xff0c;你可以从这里下载。 1&#xff1a;netassist使用 我们需要一个server程序&#xff0c;可以参考这篇文章&#xff0c;启动server后&#xff0c;就…

系列:水果甜度个人手持设备检测-产品规划的方案和实现思路

系列:水果甜度个人手持设备检测 -- 产品规划的方案和实现思路 背景 我们在前面篇章中&#xff0c;大致的检索了一下市面存在的产品&#xff0c;并采用启发性搜索的办法从国家知识产权局的专利库、中国知网CNKI的学术文献库、各种文章、论坛甚至是GitHub中对我们预研的方向进…

EmguCV学习笔记 VB.Net 2.S 特别示例

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 教程VB.net版本请访问&#xff1a;EmguCV学习笔记 VB.Net 目录-CSDN博客 教程C#版本请访问&#xff1a;EmguCV学习笔记 C# 目录-CSD…

【区块链+金融服务】中国银联区块链可信存证服务 | FISCO BCOS应用案例

随着金融行业信息化的快速推进&#xff0c;“互联网 金融”业务产生了海量的电子数据。例如&#xff0c;截止到 2022 年第二季度&#xff0c; 全国累计信用卡发卡数量约 8.07 亿张&#xff0c;累计银行卡应偿信贷余额为 8.66 万亿元&#xff0c;累计信用卡逾期半年未尝信贷 总…

盲盒抽奖源码

介绍&#xff1a; 功能上还可以,商品和盲盒可以在你程序里添加&#xff0c;设置概率等!! 新盲盒星球抽奖商城手机网站源码 随机开箱抢购 代码有点大&#xff0c;三百多M。 教程搭建很简单&#xff0c;基本10分钟搭建一套&#xff0c;可一个服务器搭建多套&#xff0c;只要你…

云计算实训31——playbook(剧本)基本应用、playbook常见语法、playbook和ansible操作的编排

playbook(剧本): 是ansible⽤于配置,部署,和管理被控节点的剧本。⽤ 于ansible操作的编排。 使⽤的格式为yaml格式 一、YMAL格式 以.yaml或.yml结尾 ⽂件的第⼀⾏以 "---"开始&#xff0c;表明YMAL⽂件的开始(可选的) 以#号开头为注释 列表中的所有成员都开始于…