1.344反转字符串
就是双指针从两边同时向中间移动。
class Solution {
public:
void reverseString(vector<char>& s) {
int n = s.size();
for(int i = 0;i<n/2;i++){
char tmp = s[i];
s[i] = s[n-1-i];
s[n-1-i] = tmp;
}
}
};
2.541反转字符串二
在前面的基础上进行一些修改,就是添加了一个left和right,用于确认翻转的范围。
注意事项:
·对到达字符串尾的处理,分为两种情况,第一种情况就是这个参与翻转即i+k<n,不参与翻转。
·这个里面每次累加的2k而不是1,因为每次2k个是作为一个整体来进行操作的。
class Solution {
public:
string reverseStr(string s, int k) {
int n = s.size();
for(int i = 0;i<n;i += 2*k){
if(i+k<n){
s = reverseStr(s,i,i+k-1);
}else{
s = reverseStr(s,i,n-1);
}
}
return s;
}
//设计的区间是左闭右闭的
string reverseStr(string s,int left,int right){
while(left<right){
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
return s;
}
};
3.替换数字
两种方法:
1.正向遍历
用一个新的变量存储返回值,此时我们遍历遇到的时候直接替换即可。
2.反向遍历
我们先确定数字有多少个,分配新的内存空间。然后反向遍历。画图可以知道,我们反向遍历(原本的长度)的时候覆盖(新的长度开始覆盖)是不会影响对应的原来的值的。
知识点:双指针
fast:指向原来的位置进行遍历,slow指向重新分配的内存空间的位置。
#include<iostream>
using namespace std;
int main(){
string s;
cin>>s;
/*
string ret;
char swaps[]="number";
for(auto num:s){
if(num <='9'&&num>='0'){
for(int i = 0;i<6;i++){
ret += swaps[i];
}
}else{
ret += num;
}
}*/
int n = s.size();
int k = n;
char swaps[]="number";
for(auto num:s){
if(num <='9'&&num>='0'){
k +=5;//因为一个替代就需要添加五个内存空间
}
}
s.resize(k);//重新确定内存空间
//从后往前覆盖,一定不会出现超过的情况
int slow = k-1;
for(int fast = n-1;fast>=0;fast--){
if(s[fast]<='9'&&s[fast]>='0'){
for(int i = 5;i>=0;i--){//替换
s[slow--] = swaps[i];
}
}else{
s[slow--] = s[fast];
}
}
cout<<s<<endl;
return 0;
}
4.反转字符串中的单词
这题应该是今天当中算最难的题目了。
思路:首先删除空格,然后整体反转,然后根据一个一个单词进行反转。
难点与实现
1.删除空格:删除空格的时候我们采取的是一个双指针的方式,一个用于遍历,另外一个用于生成新的,第一个if(if1)保证当前进入的是一个非空的字符,然后下面的while循环用于找到第一个非空或结束,然后移动,此时第一个if用于保证去除多余的空格,再然后第二个if(if2)用于补充一个空格。
2.单词反转:这个相对比较简单,只需要判断新的字符串里面遇到空格或者结尾的时候以这个为整体来进行翻转即可。确定反转范围。
class Solution {
public:
void reverseWord(string& s,int left,int right){
while(left<right){
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
}
string reverseWords(string s) {
int n = s.size();
int slow = 0;
//首先是删去空格
for(int fast = 0;fast<n;fast++){
//什么情况下进行赋值
if(s[fast]!=' '){
if(slow!=0)s[slow++]=' ';
while(fast<n&&s[fast]!=' '){//遇到的一个字母
s[slow++] = s[fast++];//继续向后
}
}
}
s.resize(slow);
cout<<s<<endl;
//其次是整体翻转
int left = 0,right = slow-1;
while(left<right){
char tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
cout<<s<<endl;
//再然后就是每个单词的翻转
left = 0;
right = slow-1;
for(int i = 0;i <= slow;i++){
if(i == slow||s[i]==' '){
right = i-1;
reverseWord(s,left,right);
left = i+1;
}
}
return s;
}
};
5.右旋字符串
两种方法:
一种是类似于字母的异位词,我们将原本那么复制一份放到最后,然后确定一个位置,直接重新赋值即可。
第二种类似于前面的,三次旋转,使用系统自带的reverse即可,只需要确定反转的范围即可。
注意事项:reverse里面的实现对应的是左闭右开的空间。
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int k;
cin>>k;
string s;
cin>>s;
int n = s.size();
s += s;
int j = 0;
for(int i = n-k;i<2*n-k;i++){
s[j++]= s[i];
}
s.resize(n);
//reverse(s.begin(),s.end());
//reverse(s.begin(),s.begin()+k);
//reverse(s.begin()+k,s.end());
std::cout << s << std::endl;
return 0;
}