目录
一、344. 反转字符串
题目链接:力扣
文章讲解:代码随想录
视频讲解:字符串基础操作! | LeetCode:344.反转字符串
题目:
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
代码:
class Solution {
public:
void reverseString(vector<char>& s) {
int left = 0, right = s.size()-1;
while(left<right)
swap(s[left++], s[right--]);
return ;
}
};
时间复杂度: O(n) 空间复杂度: O(1)
⏲:1:28
总结:reverse(s.begin(), s.begin());//左开右闭。
swap的两种写法:
//写法1
int tmp = s[i];
s[i] = s[j];
s[j] = tmp;
//写法二(位运算)
s[i] ^= s[j];
s[j] ^= s[i];
s[i] ^= s[j];
二、541. 反转字符串 II
题目链接:力扣
文章讲解:代码随想录
视频讲解:字符串操作进阶! | LeetCode:541. 反转字符串II
题目:给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。 如果剩余字符少于 k 个,则将剩余字符全部反转。 如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
代码:
class Solution {
public:
string reverseStr(string s, int k) {
int size = s.size();
for(int i = 0; i < size; i+=2*k){
int left = i, right = min(i+k-1, size-1);
while(left < right)
swap(s[left++], s[right--]);
}
return s;
}
};
时间复杂度: O(n) 空间复杂度: O(1)
⏲:5:04
总结:只需要寻找起点,分类的两种情况只有末尾不同,可以合并。
三、卡码网:54.替换数字
题目链接:54. 替换数字(第八期模拟笔试)
文章讲解:代码随想录
题目:请实现一个函数,把字符串 s
中的每个空格替换成"%20"。
代码:
#include<bits/stdc++.h>
using namespace std;
void fun(string &s){
int num = 0;
int size = s.size();
for(int i = 0;i < size;i++){
if(s[i] >= '0' && s[i] <= '9')
num++;
}
s.resize(num*5 + size);
for(int front = size-1, rear = size+num*5-1; front < rear; front--,rear--)
{
if (s[front] >= '0' && s[front] <= '9')
{
s[rear--] = 'r';
s[rear--] = 'e';
s[rear--] = 'b';
s[rear--] = 'm';
s[rear--] = 'u';
s[rear] = 'n';
continue;
}
s[rear] = s[front];
}
cout << s;
}
int main(){
string s;
cin >> s;
fun(s);
return 0;
}
时间复杂度: O(n) 空间复杂度: O(1)
总结:1、erase,insert的时间复杂度为O(n),故不用。
2、填充从后往前(本题),删除从前往后(见下一题)。
四、151.反转字符串中的单词
题目链接:力扣
文章讲解:代码随想录
视频讲解:字符串复杂操作拿捏了! | LeetCode:151.翻转字符串里的单词
题目:
给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
代码:
//1.删除空格 2.反转字符串 3.反转单词.
class Solution {
public:
string reverseWords(string s) {
//删除空格
int slow=0;
for (int fast=0; fast < s.size(); fast++)
{
if (s[fast] != ' ')
{
if (slow!=0) s[slow++] = ' ';
while (fast < s.size() && s[fast] != ' ') s[slow++] = s[fast++];
}
}//重新定义长度
s.resize(slow);//slow为字母数量。
//反转字符串
reverse(s.begin(), s.end());
//反转单词
for(int i = 0, j = 0; i <= s.size(); i++)
{
if(i == s.size() || s[i] == ' ')
{
reverse(s.begin() + j, s.begin() + i);
j = i + 1;
}
}
return s;
}
};
将翻转单词和删除空格结合在一起(省去一次遍历):
class Solution {
public:
string reverseWords(string s) {
int size = s.size();
int front = 0, rear = 0;
while(s[rear] == ' ')
rear++;
int left = 0, right = 0;
for(; rear < size;){
if(s[rear] == ' '){
right = front;
reverse(s.begin() + left, s.begin() + right);//左闭右开
while(s[rear+1] == ' ') rear++;
if (rear >= size) break;
s[front++] = s[rear++];
left = right+1;
}
else
s[front++] = s[rear++];
}
if (s[size-1] != ' ')
{
reverse(s.begin() + left, s.begin() + front);
front++;
}
s.resize(front-1);
reverse(s.begin(), s.begin() + front-1);
return s;
}
};
时间复杂度: O(n) 空间复杂度: O(1)
⏲:12:08
总结:char数组用/0结尾,string通过size判断,要删去string末尾部分单词用 resize()重新定义长度达到删除效果。vector<char>同string但string重载了"+"等符号,vector<char>无。
五、55. 右旋字符串(第八期模拟笔试)
题目链接:卡码网题目链接
文章讲解:代码随想录
视频讲解:字符串:花式反转还不够!
题目:
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
代码:
#include<bits/stdc++.h>
using namespace std;
void fun(int n, string &s){
int size = s.size();
reverse(s.begin(), s.begin() + size);
reverse(s.begin(), s.begin() + n);
reverse(s.begin()+n, s.begin() + size);
cout << s;
return;
}
int main(){
int n = 0;
string s;
cin >> n;
cin >> s;
fun(n,s);
return 0;
}
时间复杂度: O(n) 空间复杂度: O(1)
总结:1、字符串反转,可通过局部加全局反转达到效果。
2、右旋和左旋区别只有区间不同。