(8/60)反转字符串、反转字符串Ⅱ、替换数字、翻转字符串里的单词、右旋转字符串

反转字符串

leetcode:344. 反转字符串

双指针法

思路

双指针中间靠拢,靠拢过程同时引入第三只被子以交换两个杯子的水。

复杂度分析

时间复杂度:O(N)。遍历一遍字符串

空间复杂度:O(1)。

注意点

  1. while条件是left < right
  2. 可以用swap()函数交换两个数的值。

代码实现

class Solution {
public:
// 双指针法
void reverseString(vector<char>& s) {
int left = 0;
int right = s.size() - 1;
while(left < right){
char temp = s[left];
s[left++] = s[right];
s[right--] = temp;
}
}
};
// ---------------升级版-----------------------
void reverseString(vector<char>& s) {
for (int i = 0, j = s.size() - 1; i < s.size()/2; i++, j--) {
swap(s[i],s[j]);
}
}

反转字符串Ⅱ

leetcode:541. 反转字符串 II

迭代法

思路

剩余字符数量>=k为一组,对前k个字符进行reverse操作;不足k为另一组,反转剩余所有字符。

复杂度分析

时间复杂度:O(N)。

空间复杂度:O(1)。

注意点

  1. 不要下意识就写i++,步长要使用合适的值。
  2. reverse(),传入参数为始、末迭代器,左闭右开。

代码实现

class Solution {
public:
string reverseStr(string s, int k) {
// 步长为2*k
for(int i = 0;i < s.size();i += 2*k){
// 剩余字符>=k个,反转前k个字符
if(s.size() - i>= k){
reverse(s.begin() + i,s.begin()+ i + k);
}else{
reverse(s.begin()+i,s.end());
}
}
return s;
}
};

替换数字

卡码网:替换数字(第八期模拟笔试)

双指针法

思路

  1. 根据数字个数,计算变换后的字符串大小并更改。
  2. 双指针从后往前遍历,如果是非数字,则前指针赋值给后指针;否则后指针从后往前倒置入"number"

复杂度分析

时间复杂度:O(N)。

空间复杂度:O(1)。

注意点

  1. 字符串s.resize(),改变字符串大小。

代码实现

#include<iostream>
using namespace std;
int main(){
string s;
while(cin >> s){
int count = 0;
for(int i = 0;i < s.size();i++){
// 统计数字个数
if(s[i] >= '0' && s[i] <= '9'){
count++;
}
}
int oldSize = s.size();
// 重新分配字符串大小
s.resize(s.size() + count*5);
int newSize = s.size();
for(int i = oldSize - 1,j = newSize - 1;
i < j; i--,j--){
// 如果是字符,则复制过去
if(s[i] > '9' || s[i] < '0'){
s[j] = s[i];
}else{
s[j] = 'r';
s[j - 1] = 'e';
s[j - 2] = 'b';
s[j - 3] = 'm';
s[j - 4] = 'u';
s[j - 5] = 'n';
j-=5;
}
}
cout << s <<endl;
}
}

反转字符串中的单词

leetcode:151. 反转字符串中的单词

双指针法

思路

核心问题:去除多余空格

满足单词倒序只需:字符串整体反转,再反转串中的单词。

  1. 除第一个单词外
  2. fast指针移动到非空字符,

复杂度分析

时间复杂度:O(N)。去除空格遍历字符串一次;整个字符串反转遍历字符串一次;每个单词反转也遍历字符串一次。

空间复杂度:O(1)。

注意点

  1. 位运算也可以交换两数
  2. 访问数组下标前一定要确保下标在数组范围内。

代码实现

class Solution {
public:
// 左闭右闭
void reverseStr(string& s,int left,int right){
if(right < s.size()){
while(left < right){
swap(s[left++],s[right--]);
}
}
}
// 双指针法
string reverseWords(string s) {
vector<string> str;
// 首先去除多余空格
// 然后整体反转一次,再对单词反转一次
int slow = 0;
int fast = 0;
// ----------去除多余空格-----------
while(fast < s.size()){
while(s[fast] == ' ') // fast找非' '
fast++;
// fast不是字符串末端时单词前填' '
if(fast < s.size() && slow > 0)
s[slow++] = ' ';
// 填充非空字符
while(fast < s.size() && s[fast] != ' '){
s[slow++] = s[fast++];
}
}
s.resize(slow);
// ----------去除多余空格-----------
reverseStr(s,0,s.size()-1);
// ----------反转单词---------------
slow = 0;
fast = 0;
while(fast < s.size()){
//
while(fast < s.size() && s[fast] != ' '){
fast++;
}
// 反转单词
reverseStr(s,slow,fast - 1);
slow = fast + 1;
fast = slow;
}
// ----------反转单词---------------
return s;
}
};

右旋字符串

卡码网:右旋字符串(第八期模拟笔试)

反转字符串法

思路

可以看做是两段字符串调换位置,利用反转字符串里的单词的方法。

复杂度分析

时间复杂度:O(N)。reverse的时间复杂度为O(N)。

空间复杂度:O(1)。

注意点

  1. reverse()在algorithm头文件中。

代码实现

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int k = 0;
string s = "";
cin >> k;
cin >> s;
reverse(s.begin(),s.end());
reverse(s.begin(),s.begin() + k);
reverse(s.begin() + k, s.end());
cout << s << endl;
}
posted @   Tazdingo  阅读(2245)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
点击右上角即可分享
微信分享提示