【C++】string的9道OJ题
要么庸俗,要么孤独…
文章目录
- 一、仅仅反转字母
- 二、字符串中的第一个唯一字符(计数排序的思想)
- 三、字符串相加(做好加进位的工作即可)
- 四、把字符串转换成整数
- 五、反转字符串中的单词 III
- 六、字符串相乘(高精度算法:大数乘法)
- 七、验证一个字符串是否为回文
- 八、反转字符串 II(反转字符串2k区间的前k个字符)
- 九、字符串中最后一个单词的长度(getline()的使用)
一、仅仅反转字母
1.
这道题的难度算非常简单的了,我们可以定义两个变量来表示数组首尾位置的有效字符的下标,然后分别从前和从后向中间遍历,只要遇到字母就停下来,利用库函数swap进行交换。
class Solution {
public:string reverseOnlyLetters(string s) {size_t begin=0,end=s.size()-1;while(begin<end){while(begin<end && !isalpha(s[begin]))//字符串有可能全不是字母,begin要保证小于end,否则陷入死循环{++begin;}while(begin<end && !isalpha(s[end])){--end;}swap(s[begin],s[end]);++begin;--end;}return s;}
};
二、字符串中的第一个唯一字符(计数排序的思想)
1.
这道题利用了计数排序的思想,每一个字母对应的ascll码本质都是一个数字,我们可以将这个数字看成是计数数组count的下标,然后将这个下标对应的元素+1,这样数组count中如果有某个下标对应的元素是1,则证明这个下标的ascll码反推回去的字母在原字符串中只出现了一次,然后再将字符串数组从前向后遍历一遍,看看第几个字符在计数数组里面的字符下标对应的元素是1,如果从前向后遍历的过程中遇到这样的字符,则说明这个字符就是字符串中的第一个唯一字符,然后直接返回即可。
class Solution {
public:int firstUniqChar(string s) {int count[128]={0};int size=s.size();for(int i=0;i<size;i++){count[s[i]]++;}for(int i=0;i<size;i++){if(1==count[s[i]]){return i;}}return -1;}
};class Solution {
public:int firstUniqChar(string s) {int count[26]={0};for(auto ch : s){count[ch - 'a']++;}for(int i = 0; i < s.size(); i++){if(count[s[i] - 'a'] == 1)return i;}return -1;}
};
三、字符串相加(做好加进位的工作即可)
1.
越是这样逻辑链比较长的题目,我们越应该多定义几个变量,因为有效变量越多,我们的思维负担就越小,逻辑就更加清晰。当然,多做题和阅读高级代码也是非常重要的因素,这可以帮助我们定义出多个有效的变量。
2.
对于出现两种判断情况时,要善于运用三目运算符,这可以帮助我们减少if的分支条件判断,影响我们的思维逻辑。
3.
无论是数的加减还是乘除,在计算高位时都不要忘了加上前面的进位,比头插效率更高的是尾插,我们可以先尾插成返回的结果字符串,然后利用库函数模板reverse传递字符串首尾的迭代器即可反转字符串,这样的时间复杂度是O(N),而头插的时间复杂度是O(N²)。
class Solution {
public:string addStrings(string num1, string num2) {string retstr;int carry=0;int end1 = num1.size()-1,end2 = num2.size()-1;while(end1 >= 0 || end2 >= 0){int value1 = end1 >= 0 ? num1[end1]-'0' : 0;int value2 = end2 >= 0 ? num2[end2]-'0' : 0;int ret = value1 + value2 + carry;//表示下一位计算时,要加上前面位的进位。carry = ret/10;ret %= 10;retstr.insert(0, 1, ret + '0');//用'ret'来进行头插,会发生int到char类型的截断,不要胡搞。--end1;--end2;}if(carry == 1)retstr.insert(0, 1, '1');return retstr;}
};
四、把字符串转换成整数
1.
可以从后向前进行遍历字符串,将每个字符转换成整数,然后乘上相应的位权重,这个位权重我们可以自己实现mypow函数,因为库提供的pow函数返回的是double类型的数据。最后将每一位字符对应的整数加到ret上即可。
class Solution {
public:int mypow(int num, int cnt){int ret = 1;while(cnt>0){ret *= num;cnt--;}return ret;}int StrToInt(string str) {int retnum = 0;int size = str.size();int end = str.size()-1;if(str[end] == '+' || str[end] == '-')return 0;//从后向前进行遍历,将字符对应的数字加到retnum即可while(end >= 0 && ((str[end] >= '1' && str[end] <= '9') || str[end] == '+' || str[end] == '-')){int num = (str[end] - '0') * mypow(10, size - end -1);retnum += num;--end;if(end == 0 && str[end] == '-'){retnum *= -1;return retnum;}if(end ==0 && str[end] == '+'){return retnum;}}if(end >= 0)return 0;return retnum;}
};
五、反转字符串中的单词 III
1.
这道题本质思想还是前后指针,end作为前指针,我们让他的下一个位置指向空格,并且拿一个flag记录一下空格的位置,以便于之后begin和end的迭代。
所以只要每次将begin和end之间的字符进行反转即可,反转完毕之后,让begin和end向后迭代直到最后一部分单词被反转完毕。
class Solution {
public:string reverseWords(string s) {int begin = 0, end = 0;int size = s.size() - 1;while(begin <= size && s[end] != '\0'){while(s[end+1] != ' '){if(s[end + 1] == '\0')break;++end; }int flag = end + 1;//flag是空格的位置while(begin < end){swap(s[begin++], s[end--]);}begin = flag + 1;end = begin;}return s;}
};
六、字符串相乘(高精度算法:大数乘法)
1.
利用reverse和迭代器先将两个字符串都进行反转,然后遍历其中一个字符串,由地位向高位拿出字符并且将每个字符与另一个字符串进行相乘,将相乘后的字符串结果暂时存到tmp对象里面,然后将tmp字符串错位相加到result字符串里面,第一次不用错位相加,但之后每一次相乘的结果都需要进行错位相加。
class Solution
{
public:void MulItem(string &tmp, string &num1, char a){int i = 0, sign=0;int mul = 0;while(i < num1.size()){mul = (num1[i]-'0') * (a-'0') + sign;if(mul >= 10){sign = mul / 10;mul %= 10;}elsesign = 0;tmp.push_back(mul+'0');i++;}if(sign > 0)tmp.push_back(sign+'0'); } //对应位相加,sign进位采用引用传递int AddItem(int a, int b, int &sign){int add = a+b+sign;if(add >= 10){sign = 1;add -= 10;}elsesign = 0;return add;}//错位相加void MoveAdd(string &result, string &tmp, int k){int i, j;i = k;j = 0;int sign = 0;while(i<result.size() &&j<tmp.size()){result[i] = AddItem(result[i]-'0', tmp[j]-'0', sign) + '0';i++;j++;}if( i<result.size()&&sign)//在错位相加之后,下一次的tmp字符串可能为0,这个时候需要在原有的result字符串的基础上进行上一次result和tmp字符串相加之后可能遗留下来的进位。result[i] = AddItem(result[i]-'0', 0, sign)+'0';while(j < tmp.size())//如果tmp字符串不为0,则错位相加之后,tmp字符串肯定还没有遍历完,所以还需要将剩余的字符在加到result上面去(利用push_back){int v = AddItem(0, tmp[j]-'0', sign);result.push_back(v+'0');j++;}if(sign)//最后的最后,如果在tmp的剩余字符串加完之后,还留有进位,则需要继续将进位尾插到result字符串对象里面result.push_back(sign+'0');}string multiply(string num1, string num2) {//先翻转数据,方便进位处理reverse(num1.begin(), num1.end());reverse(num2.begin(), num2.end());string tmp, result;for(int i=0; i<num2.size(); ++i){//使用num2的每一个数据乘以num1MulItem(tmp, num1, num2[i]);//将乘得的结果进行错位相加MoveAdd(result, tmp, i);tmp.clear();} while(result.size()!=1 && result.back()=='0')//如果进位之后的字符串尾部出现0,我们需要手动将其pop掉result.pop_back();//翻转数据,恢复数据reverse(result.begin(), result.end());return result;}};
七、验证一个字符串是否为回文
1.
这道题有两种解决方式,第一种就是将所有的字母和数字字符挑出来尾插到一个新的string类对象中,然后我们从对象的头和尾向中间进行遍历,判断是否为回文串。
第二种就是直接原地在原有字符串中进行比较,遍历的同时过滤掉非字母和数字的字符即可。注意判断一下没有字母或数字的情况,这样的情况我们直接返回true即可。
class Solution {
public:bool isPalindrome(string s) {// string palin_array;// int begin1 = 0, end1 = s.size() - 1;// //1.先将字符串中大写字母替换为小写字母// for(int i = begin1; i <= end1; i++)// {// if(s[i] >= 'A' && s[i] <= 'Z')// s[i] += 32;// }// //2.将字母和数字放到palin_array数组里面// for(int i = begin1; i <= end1; i++)// {// if(s[i] >= 'a' && s[i] <= 'z' || s[i] >= '0' && s[i] <= '9')// palin_array.push_back(s[i]);// }// if(palin_array.size() == 0)// return true;// int begin2 = 0, end2 = palin_array.size() - 1;// int palin_tail = palin_array.size() - 1;// //3.判断palin_array数组的字符串是否是回文// while(begin2 != palin_tail)// {// if(palin_array[begin2] != palin_array[end2])// return false;// begin2++;// end2--;// }// return true;//1.先将字符串中大写字母替换为小写字母int begin1 = 0, end1 = s.size() - 1, tail = s.size() - 1;for(int i = begin1; i <= end1; i++){if(s[i] >= 'A' && s[i] <= 'Z')s[i] += 32;}//2.在s数组里直接进行首尾元素的比较while(begin1 <= tail){while(!(s[begin1] >= 'a' && s[begin1] <= 'z' ||s[begin1] >= '0' && s[begin1] <= '9') && begin1 <= tail){begin1++;if(begin1 > tail )return true;}while(!(s[end1] >= 'a' && s[end1] <= 'z' ||s[end1] >= '0' && s[end1] <= '9') && end1 >= 0){end1--;}if(s[begin1] != s[end1]){return false;}//如果字符相等,继续进行比较begin1++;end1--;}return true;}
};
八、反转字符串 II(反转字符串2k区间的前k个字符)
1.这道题的逻辑非常的清晰,我们只需要找到凑成2k大小的字符组,然后按照前后指针的方法进行每组当中前k个字符的反转,最后剩余的字符分为两种情况分别进行处理,处理的方式也很简单,详情见代码。
2.
这道题的难度不大,但是在我做的时候,发生了一些代码逻辑的小问题,并且在我多次走读代码之后依旧找不到漏洞,所以这很是让我苦恼。
就算是调试,对于这样的接口型,我们也不好调试,因为如果要进行调试,还需要自己补充成员变量,相当的麻烦,但其实这样的接口型调试也有解决方法,我们只需要将其搞成类静态函数即可,然后在main函数里面用类名加域作用限定符调用这个静态函数即可,这样就可以轻松实现调试了,对于接口型,搞成静态这样的方法非常好用,可以不用定义类对象就能调用成语函数,岂不快哉!
3.
这里在复习一下关于类的静态成员的知识,关于类静态成员的调用方式分为两种,一种是通过对象.静态成员方式调用,一种是通过类名::静态成员的方式进行调用。
而对于非静态成员来讲,不能通过类名::的方式进行调用,因为非静态成员函数有this指针,所以在调用时必须指定调用的对象是谁,正因为如此,没有this指针的静态成员函数才可以通过类名进行调用。以此来方便我们进行调试
class Solution {
public:static string reverseStr(string s, int k) {//1.先判断这个字符串中有几个凑成2k大小的字符组,留下的字符个数是多少int group_cnt = s.size() / (2 * k);int remaining_char = s.size() % (2 * k);//2.将前group_cnt个字符组每每进行字符反转int prev_begin1 = 0, prev_end1 = k - 1;while (group_cnt--){//记录原先begin1和end1的位置,下面循环的时候,begin1和end1会发生改变int begin1 = prev_begin1, end1 = prev_end1;while (begin1 < end1){swap(s[begin1++], s[end1--]);}prev_begin1 += (2 * k);prev_end1 += (2 * k);}//3.将剩余的字符分为两种情况,然后进行反转int begin2 = s.size() - remaining_char;int end2 = s.size() - 1;if (remaining_char < k)//剩余字符全部反转{while (begin2 < end2)swap(s[begin2++], s[end2--]);}else//反转剩余字符的前k个字符{int end3 = end2 - (remaining_char - k);while (begin2 < end3)swap(s[begin2++], s[end3--]);}return s;}
};
九、字符串中最后一个单词的长度(getline()的使用)
1.这道题可以利用getline来获取一行的字符串,然后通过rfind函数找到最后一个单词前面空格的位置,最后用字符串大小(实际就是\0位置的下标)减去空格位置的下标,再减1,因为两个下标做差求的是区间的个数,要求区间中字符的个数需要多减去1.
#include <iostream>
#include <string>
using namespace std;int main()
{string str;getline(cin,str);int pos = str.rfind(' ');cout << str.size() - pos - 1 << endl;
}
相关文章:

【C++】string的9道OJ题
要么庸俗,要么孤独… 文章目录一、仅仅反转字母二、字符串中的第一个唯一字符(计数排序的思想)三、字符串相加(做好加进位的工作即可)四、把字符串转换成整数五、反转字符串中的单词 III六、字符串相乘(高…...

Odoo丨Odoo框架源码研读三:异常处理与定制化开发
Odoo丨Odoo框架源码研读三:异常处理与定制化开发 Odoo源码研读的第三期内容:异常处理与定制化开发。 *异常处理* Odoo中的Exception是对Python内置异常做了继承和封装,设定了自己核心的几个Exception。 而对异常的处理和Python内置异常的…...

Python概述 基础语法 判断 循环
Python概述常用快捷键第二章-Python基础语法01-字面量02-注释03-变量04-数据类型05-数据类型转换06-标识符07-运算符08-字符串的三种定义方式09-字符串的拼接10-字符串格式化11-字符串格式化的精度控制 12-字符串格式化-快速写法13-对表达式进行格式化14-字符串格式化练习题讲解…...

什么是品牌营销?学会正确推广您的业务
什么是品牌营销? 品牌营销涉及长期战略规划,以推广整个品牌,而不是营销单个产品或服务。它分享了一个引人入胜的故事,以在潜在客户中产生品牌知名度并建立声誉。 面向消费者的品牌使用品牌智能软件来了解人们对其品牌的看法&#…...

Golang学习Day1
😋 大家好,我是YAy_17,是一枚爱好网安的小白。本人水平有限,欢迎各位大佬指点,欢迎关注 😁,一起学习 💗 ,一起进步 ⭐ 。⭐ 此后如竟没有炬火,我便是唯一的光…...

《设计模式》工厂模式
《设计模式》工厂模式 工厂模式又分为简单工厂(Simple Factory)、工厂方法(Factory Method)和抽象工厂(Abstract Factory)都是常用的创建型设计模式,它们的主要区别如下: 简单工厂…...

JS - 原型对象、原型链是什么
一 阅读掘金 https://juejin.cn/post/7007416743215759373 https://juejin.cn/post/7007416743215759373 二 阅读掘金小册原型知识点 原型 涉及面试题:如何理解原型?如何理解原型链? 当我们创建一个对象时 let obj { age: 25 }࿰…...

STM32f103 CubeMX封装 led程序
本文代码使用 HAL 库。 文章目录前言一、LED 原理图二、CubeMX创建工程三、LED 相关函数1. 输出电平函数:2. 延时函数:3. 翻转电平函数:四、详细代码实验现象 :总结代码 源码:前言 从这篇文章开始,我们讲解…...

智慧教室系统--温湿度控制系统
随着科技的不断进步,智能化已经成为了各个行业的发展趋势,智慧教室作为未来教育的主流趋势之一,也将受益于这一趋势。而智慧教室中的温湿度控制系统是其中的重要组成部分,为了创造一个舒适、健康、安全的教学环境,智慧…...

只要一直向前定能到达远方,社科院与杜兰大学金融管理硕士项目为你注入动力
在人生这条道路上,我们很远的路要走,不管前方是否平坦,我们只要坚持前向,终将抵达远方。一路上我们付出很多,也收获很多。想要变得更强大,就要不断优化自身,积攒更多的能量,社科院与…...

Java性能-回收算法-Throughout回收算法
垃圾回收算法 理解Throughput回收器 回收器三个基本操作——回收 找到不使用的对象 释放内存 压缩堆碎片 Minor GC和Full GC,每个操作都会标记,释放和压缩对应的目标分代 [63.205s][info][gc,start ] GC(13) Pause Full (Ergonomics) [63.205s][info][…...

立项近7年,索尼产品经理分享PS VR2开发背后的故事
备受期待的索尼PS VR2终于正式发售,VR爱好者们终于有机会体验到《地平线:山之呼唤》等PS VR2独占的VR大作。近期,为了解PS VR2头显诞生背后的故事,外媒AV Watch采访到PS VR2的开发负责人Yasuo Takahashi,在本次采访中&…...

Kubernetes 如何通过ingress-nginx实现应用灰度发布?
在日常的工作中,我们会经常对应用进行发版升级,在互联网公司尤为频繁,主要是为了满足快速的业务发展。我们经常用到的发布方式有滚动更新、蓝绿发布、灰度发布。滚动更新:依次进行新旧替换,直到旧的全部被替换为止。蓝…...

华为OD机试 - 密室逃生游戏(Java) | 机试题+算法思路+考点+代码解析 【2023】
密室逃生游戏 小强增在参加《密室逃生》游戏,当前关卡要求找到符合给定 密码K(升序的不重复小写字母组成) 的箱子, 并给出箱子编号,箱子编号为 1~N 。 每个箱子中都有一个 字符串s ,字符串由大写字母、小写字母、数字、标点符号、空格组成, 需要在这些字符串中找到所有…...

redis的主从复制细节
文章目录复制机制的运作复制的一些事实master持久化关闭时,复制的安全性Redis复制是如何工作的只读性质的slave设置一个slave对master进行验证允许只写入N个附加的副本Redis如何处理过期键重新启动和故障转移后的部分同步复制机制的运作 master和slave的复制运作依…...

SparkSQL
第1章 SparkSQL 概述1.1 SparkSQL 是什么Spark SQL 是 Spark 用于结构化数据(structured data)处理的 Spark 模块。1.2 Hive and SparkSQLSparkSQL 的前身是 Shark,给熟悉 RDBMS 但又不理解 MapReduce 的技术人员提供快速上手的工具。Hive 是早期唯一运行在 Hadoop …...

Python|每日一练|栈|数组|字典树|数组|树|广度优先搜索|单选记录:逆波兰表达式求值|回文对|二叉树的层序遍历
1、逆波兰表达式求值(栈,数组) 根据 逆波兰表示法(https://baike.baidu.com/item/%E9%80%86%E6%B3%A2%E5%85%B0%E5%BC%8F/128437),求表达式的值。 有效的算符包括 、-、*、/ 。每个运算对象可以是整数,也可以是另一个…...

慧教室系统--远程控制系统
随着科技的不断进步,越来越多的教育机构开始使用智慧教室系统来提升教学效果和学生体验。智慧教室系统不仅可以自动化管理设备,还可以实现远程控制,帮助教师和学生更加便捷地使用教室设备。智慧教室系统作为一款领先的智慧教育解决方案&#…...

OSCP-课外1(http万能密码、hydra密码暴力破解http、代码审计、Win缓存区溢出)
目录 难度 主机发现&端口扫描 信息收集 万能密码 hydra密码暴力破解...

ELK日志分析--Logstash
Logstash简介 Logstash安装 测试运行 配置输入和输出 使用Geoip过滤器插件增强数据编辑 配置接收 Beats 的输入 1.Logstash简介 Logstash管道具有两个必需元素input和output,以及一个可选元素filter。输入插件使用来自源的数据,过滤器插件根据你的…...

Mysql插入数据从指定选项中随机选择、插入时间从指定范围随机生成、Navicat使用存储过程模拟插入测试数据
场景 Navicat通过存储过程批量插入mysql数据: Navicat通过存储过程批量插入mysql数据_霸道流氓气质的博客-CSDN博客 上面使用过Navicat借助存储过程批量插入数据。但是插入数据是固定的 insert语句,如果在本地开发时需要模拟插入一些随机数据(从指定…...

【基础算法】关于高精度计算的问题【很高位数数据的加减乘除(相关代码用C++实现)】
文章目录前言1.高精度加法2.高精度减法3.高精度乘法4.高精度除法写在最后前言 当我们在利用计算机进行一些计算时,可能会遇到这类问题 : 有些计算要求精度高,希望计算的数的位数可达几十位甚至几百位,虽然计算机的计算精度也算较…...

事理知识图谱
事理知识图谱能够有力第建模各类事件之间的演化关联关系为事理逻辑推理提供更好的数据基础。 事理图谱定义 事理知识图谱可以将文本中对事件以及事件之间的关系抽取并抽象出来,构建成一个有向图形式的事理知识库。在结构上,事理知识图谱是一个有向有环…...

多綫程之python爬蟲構建
目录多綫程定義簡介原理优点缺点优势代碼框架實現導包打印類爬蟲類構造方法獲取代理設置headers獲取新session獲取源代碼解析網頁解析子頁面保存數據綫程任務得到url啓動多綫程爬蟲總結多綫程 以下定義來自百度百科,看看就好沒仔細寫 定義 多线程(mul…...

【干货】Redis在Java开发中的基本使用和巧妙用法
Redis是一款高性能的内存数据结构存储系统,能够支持多种数据结构类型,如字符串、哈希、列表、集合、有序集合等,也能够支持高级功能,如事务、发布/订阅、Lua脚本等,具有高可用性、高并发性和可扩展性的优点。在Java开发…...

历时半年,我终于阿里上岸了,附面经和Java非科班学习心得
个人经历 本科双非化学,跨考了电子硕士,研究生依然双非。无互联网实习,无比赛无论文。(研究生研究方向是车辆电子和楼宇自动化,有自动化和高校实训讲师相关的实习经历) 21年11开始学Java准备秋招。 阿里上…...

ArkUI实战,自定义饼状图组件PieChart
本节笔者带领读者实现一个饼状图 PieChart 组件,该组件是根据笔者之前封装的 MiniCanvas 实现的, PieChart 的最终演示效果如下图所示: 饼状图实现的拆分 根据上图的样式效果,实现一个饼状图,实质就是绘制一个个的实…...

工作实战之系统交互api调用认证设计
目录 前言 一、黄金段位接口交互 二、钻石段位接口交互设计 1.接口文档定义 2.工具类以及demo提供 a.调用方部分代码 b.被调用方 三.星耀段位接口访问设计 1.在钻石段位的基础上,进行sdk的封装 a.maven引入 b.sdk包含工具类 四.王者段位接口访问设计 1.开发详情 2.…...

学习系统编程No.5【虚拟地址空间】
引言: 北京时间:2023/2/22,离补考期末考试还有5天,不慌,刚午觉睡醒,闹钟2点20,拖到2点50,是近以来,唯一一次有一种睡不醒的感觉,但是现在却没有精神,因为听了…...

Linux常用指令(未完待续。。。)
* basename:只留下路径的“最后一部分” X、文件夹&目录操作 复制 :cp /xxx /xxx - a 该选项通常在拷贝目录时使用。它保留链接、文件属性,并递归地拷贝目录,其作用等于dpR选项的组合; - d 拷贝时保留链接&#…...