一、翻转字符串||
1.题目
2.思路
这道题其实就是要翻转每部分前k个字符
在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。
3.代码
class Solution {
public:
string reverseStr(string s, int k) {
//i每次进行2k的遍历
for(int i = 0;i<s.size();i+=(2*k)){
//对前k个进行翻转
//后面不够2k,但是大于等于k,对前k个进行翻转
if(i+k < s.size()){
reverse(s.begin()+i,s.begin()+i+k);//reverse函数左闭右开
}
else{//剩余的不够k个直接全部翻转
reverse(s.begin()+i,s.end());
}
}
return s;
}
};
二、替换数字
1.题目
54. 替换数字(第八期模拟笔试) (kamacoder.com)
给定一个字符串 s,它包含小写字母和数字字符,请编写一个函数,将字符串中的字母字符保持不变,而将每个数字字符替换为number。
例如,对于输入字符串 "a1b2c3",函数应该将其转换为 "anumberbnumbercnumber"。
对于输入字符串 "a5b",函数应该将其转换为 "anumberb"
输入:一个字符串 s,s 仅包含小写字母和数字字符。
输出:打印一个新的字符串,其中每个数字字符都被替换为了number
样例输入:a1b2c3
样例输出:anumberbnumbercnumber
数据范围:1 <= s.length < 10000
2.思路
在不开辟一个新的字符串的情况下进行数字替换。
- 要对字符串中的数字进行遍历,统计个数,字符串resize出空位置
- 双指针从后往前进行替换:旧指针指向旧字符串末尾的位置,新字符串指向新字符串末尾的位置。旧指针开始遍历替换。
为什么从后面开始遍历呢?
- 不用申请新数组。
- 从后向前填充元素,避免了从前向后填充元素时,每次添加元素都要将添加元素之后的所有元素向后移动的问题。
3.代码
#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--;
}
std::cout << s << std::endl;
}
}
三、翻转字符串里的单词
1.题目
2.思路
- 移除多余空格
需要考虑移除字符串头部空格,单词之间的空格,字符串结尾的空格
- 将整个字符串反转
为了整体代码空间复杂度为O(1)
- 将每个单词反转
3.代码
class Solution {
public:
//移除冗余空格
void RemoveExtraSpace(string &s){
//双指针保留所有单词,不同单词中间只留一个空格
//快指针指到了字符,说明结束位置需要一个空格分割
int slow=0,fast=0,need=false;
for(;fast<s.size();fast++){
if(s[fast] != ' '){
s[slow++] = s[fast];
need = true;
continue;
}
if(need){
s[slow++] = ' ';
need = false;
}
}
//
if(s[slow-1] == ' '){
s.resize(slow-1);
}
else{//这一句是为了限制去除空格后的字符串大小,防止后面整体翻转错误
s.resize(slow);
}
}
//编写翻转函数,方便后续单词翻转
void reverse(string &s,int start,int end){
for(int i = start,j = end;i<j;i++,j--){
swap(s[i],s[j]);
}
}
string reverseWords(string s) {
reverse(s,0,s.size()-1);
RemoveExtraSpace(s);
int i = 0;
int count = i;
for(;i<s.size();i++){
if(s[i] == ' '){
reverse(s,count,i-1);
count = i+1;
}
else if(i == s.size()-1){
reverse(s,count,i);
}
}
return s;
}
};
四、右旋字符串
1.题目
55. 右旋字符串(第八期模拟笔试) (kamacoder.com)
字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。
例如,对于输入字符串 "abcdefg" 和整数 2,函数应该将其转换为 "fgabcde"。
2.思路
进行三次翻转即不用另外开辟空间。
第一次进行整体翻转
第二次对前n个进行翻转(此时的前n个是原字符串后面的n个)
第三次对剩余部分进行翻转即可获得要求字符串
3.代码
#include <iostream>
using namespace std;
void reverse(string& s, int start, int end){ //翻转,区间写法:左闭右闭 []
for (int i = start, j = end; i < j; i++, j--) {
swap(s[i], s[j]);
}
}
int main(){
int n;
cin >> n;
string s;
cin >> s;
int len = s.size();
reverse(s,0,len-1);
reverse(s,0,n-1);
reverse(s,n,len-1);
std::cout << s << std::endl;
}