一、前言
今天进入字符串的第二题,这个题是卡哥的网站里自带的,并不在力扣里,因此也比较具有刷的意义。这个题看起来很简单,但是第一次做起来还是很难想的,原来这么做才是清楚、明白的方法。我觉得这也是我们所需要的能力。话不多说,开始题目。
二、题目(替换数字54. 替换数字(第八期模拟笔试))
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。
实例:
输入:a1b2c3
输出:anumberbnumbercnumber
三、题解
先把卡哥的思路放在这里(代码随想录)大家自行去看卡哥的讲解,很详细、直白。我最开始的思路是从正向扫描,然后扫描到数字则将数字之前的复制到一个新的字符串中,并在尾部插入“number”,然后接着向后扫描旧的字符串。我只能说我的思路是好的,但是过于麻烦而且过于复杂。当我看见了卡哥的思路后,我一下子就接受了并且自己试着写出了代码,我认为卡哥的思路是比较便于理解(在原有的基础上)。那么我就讲讲我对卡哥思路的理解。
代码(因为是ACM模式,所以是完整的程序):
#include<bits/stdc++.h>
using namespace std;
int main(){
string s;
cin>>s;
int co=0;
int len=s.size();
for(int i=0;i<len;i++){//判断s中有几个数字
if(s[i]>='0'&&s[i]<='9'){
co++;
}
}
s.resize(s.size() + co * 5);//扩大s的长度,co*5是因为原来的数字还占了1个单位所以是5而不是6
int left=len-1;//原字符串末尾位置
int right=s.size()-1;//扩大后字符串的末尾位置
while(left<right){
if(not isdigit(s[left])){//如果不是数字,则把字符串移到新字符串的后面
s[right]=s[left];
left--;
right--;
}
else{//若是数字,则在新字符串倒着写number
s[right]='r';right--;
s[right]='e';right--;
s[right]='b';right--;
s[right]='m';right--;
s[right]='u';right--;
s[right]='n';right--;
left--;
}
}
cout<<s<<endl;
return 0;
}
我就讲讲我对于核心代码的理解吧。
while(left<right){
if(not isdigit(s[left])){//如果不是数字,则把字符串移到新字符串的后面
s[right]=s[left];
left--;
right--;
}
else{//若是数字,则在新字符串倒着写number
s[right]='r';right--;
s[right]='e';right--;
s[right]='b';right--;
s[right]='m';right--;
s[right]='u';right--;
s[right]='n';right--;
left--;
}
}
首先是确定好left和right的位置,两者都是字符串的末尾位置,然后则是在原字符串从后向前扫描,若扫描的不是数字,则将该字母放到新字符串的后面,然后left和right都向前移动(接着扫描);若是数字,则将新字符串中的right位置从后向前写“number”(也就是倒着写number),这样就相当于替换了数字。卡哥核心的思路就是一个双指针,只是两个指针不再指向同一个数据结构的两端。请各位uu自行体会,好好自己练习吧。
四、后记
刷惯了力扣的算法模式,突然对于ACM模式还有些不知道如何处理输入、输出,因此我们也要加强对ACM模式的练习。然后就是对于算法的熟悉和练习我觉得是必要的,最后就是希望各位能够坚持,我们都会有自己的进步,我们都会有光明的未来!!!