卡码 54 替换数字
题目描述
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。
例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。
输入描述
输入一个字符串 s,s 仅包含小写字母和数字字符。
输出描述
打印一个新的字符串,其中每个数字字符都被替换为了number
输入示例
a1b2c3
输出示例
anumberbnumbercnumber
提示信息
数据范围:
1 <= s.length < 10000
新建字符串法
通过新建结果字符串,逐个遍历原字符,字母直接追加,数字追加"number"
✅新建字符串法的完整代码:
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cin >> s;
string res;
for (char c : s) {
if (isdigit(c)) {
res += "number";
} else {
res += c;
}
}
cout << res << endl;
return 0;
}
核心思路:
- 新建结果字符串
res,用于不断存储替换后的结果 for循环遍历原字符串,逐个判断各字符- 如果当前字符为数字,
res追加number,其中数字判断通过isdigit函数 - 如果当前字符为小写字母,则
res追加原字符 - 最后输出
res结果字符串
关于代码中的 for(char c : s):
这种写法是C++11的写法,实际上与普通for循环是等效的,只是更为简洁,如下:
// 普通for循环写法
for(int i = 0;i < s.size();i++){
char c = s[i];
}
// C++11标准下for循环写法
for(char c : s){}
新建字符串法的优点在于简洁易懂,代码更容易,但缺点是开辟了新字符串内存
双指针法
要想原地实现替换,就需要使用双指针法。
其核心思路是先扩充数组,然后利用双指针,一前一后分别从后向前遍历数组并不断按要求完成替换,原理如下:
✅双指针法的完整代码:
#include <iostream>
using namespace std;
int main() {
string s;
while (cin >> s) {
int sOldIndex = s.size() - 1;
int count = 0; // 用于记录数字出现的次数
for (int i = 0; i < s.size(); i++) {
if (s[i] >= '0' && s[i] <= '9') {
count++;
}
}
s.resize(s.size() + count * 5); // 扩充数组
int sNewIndex = s.size() - 1;
while (sOldIndex >= 0) {
if (s[sOldIndex] >= '0' && s[sOldIndex] <= '9') {
s[sNewIndex--] = 'r';
s[sNewIndex--] = 'e';
s[sNewIndex--] = 'b';
s[sNewIndex--] = 'm';
s[sNewIndex--] = 'u';
s[sNewIndex--] = 'n';
} else {
s[sNewIndex--] = s[sOldIndex];
}
sOldIndex--;
}
cout << s << endl;
}
}
为什么是从后往前填充而不是从前往后?
核心原因在于从前向后填充就是 的算法了,因为每次添加元素都要将添加元素之后的所有元素整体向后移动。
这样利用双指针法有两个好处:
- 不用申请新数组。
- 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。