代码随想录Day8 | 344.反转字符串 541. 反转字符串II 卡码网:54.替换数字 151.翻转字符串里的单词 卡码网:55.右旋转字符串
反转字符串
文档讲解:代码随想录
视频讲解: 字符串基础操作! | LeetCode:344.反转字符串
状态:√
双指针,头和尾扫描到然后交换,直到两指针相等。
class Solution {
public:
void reverseString(vector<char>& s) {
//双指针
int left = 0;
int right = s.size()-1;
while(left<right)
{
char temp;
temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
}
};
反转字符串II
文档讲解:代码随想录
视频讲解: 字符串操作进阶! | LeetCode:541. 反转字符串II
状态:√
同样是双指针,只不过如何判断取右指针以及边界控制是需要考虑的。
- 以左指针为基数,进行主循环,每次循环结束左指针+2k
- 右指针边界就是左指针+k-1
- 一次循环中如果右指针小于字符串最后一位,说明可以翻转k个。
- 当右指针大于字符串最后一位,就翻转剩下所有
- 由于左指针每次+2k所以不需要考虑后面k个数
class Solution {
public:
string reverseStr(string s, int k) {
int left = 0;
for(left;left<s.length();left+=2*k)
{
if(left+k<=s.length())
{
int tl = left;
int tr = tl+k-1;
while(tl<tr)
{
swap(s[tl],s[tr]);
tl++;
tr--;
}
}
else
{
int tl = left;
int tr = s.length()-1;
while(tl<tr)
{
swap(s[tl],s[tr]);
tl++;
tr--;
}
}
}
return s;
}
};
时间复杂度: O ( n / k ∗ k ) = O ( n ) O(n/k * k) = O(n) O(n/k∗k)=O(n)
卡码网:54.替换数字
文档讲解:代码随想录
视频讲解:
状态:×
先扩充字符串,然后从后向前匹配,避免从前向后匹配时,后面字符的移动
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s;
cin >> s;
int num_count = 0;
int size = s.length();
int count = 0;
while(count<size)
{
if(s[count]>='0'&&s[count]<='9')
{
num_count++;
}
count++;
}
s.resize(s.length()+num_count*5);
int right = size-1;
int new_right = s.length()-1;
while(right<new_right&&right>=0)
{
if(s[right]>='0'&&s[right]<='9')
{
s[new_right--] = 'r';
s[new_right--] = 'e';
s[new_right--] = 'b';
s[new_right--] = 'm';
s[new_right--] = 'u';
s[new_right--] = 'n';
}
else
{
s[new_right--] = s[right];
}
right--;
}
for(int i = 0;i<s.length();i++)
{
cout << s[i];
}
return 0;
}
151.翻转字符串里的单词
文档讲解:代码随想录
视频讲解: 字符串复杂操作拿捏了! | LeetCode:151.翻转字符串里的单词
状态:√
先按照空格分别翻转字符串,然后再逆序填入返回的字符串中。在填入的过程中处理多余空格的情况。
class Solution {
public:
string reverseWords(string s) {
//处理头尾空格
int left = 0;
int right = s.length()-1;
while(s[left] == ' ') left++;
while(s[right] == ' ') right--;
string resstr;
//记录第一个字符串的头
int begin = left;
//按空格分割翻转,然后再逆序输出到resstr
for(int i= left;i<=right;)
{
//遇到第一个空格进行翻转和跨过空格的操作
if(s[i] == ' ' && s[i-1] != ' ')
{
int temp = i-1;
while(begin<temp)
{
swap(s[begin],s[temp]);
begin++;
temp--;
}
//跨过空格
while(s[i+1] == ' ')
{
i++;
}
//更改为下一个字符串的头
begin = i+1;
}
//处理最后一个字符串的情况
else if(i == right)
{
int temp = i;
while(begin<temp)
{
swap(s[begin],s[temp]);
begin++;
temp--;
}
}
//如果不是空格也不是最后一个字符串自增
i++;
}
//逆序填入
for(int i=right;i>=left;)
{
//如果不是空格直接填
if(s[i]!=' ')
{
resstr+=s[i];
}
//如果是空格
else
{
//填入一个空格
resstr+=' ';
//如果其后面仍然是空格,跳过
while(s[i-1]==' ')
{
i--;
}
}
//自减
i--;
}
return resstr;
}
};
时间复杂度: O ( n 2 ) O(n^2) O(n2)
- 整理字符串,删除空格,翻转,以空格分隔翻转
class Solution {
public:
string& reverse(string& s,int begin,int end)
{
while(begin<end)
{
swap(s[begin],s[end]);
begin++;
end--;
}
return s;
}
//同删除元素
string& ClearSpace(string& s)
{
int left = 0;
for(int i = 0;i<s.length();i++)
{
if(s[i]!=' ')
{
//当上一次循环结束,s[i] == ' '
//如果此时的left不是0,那说明需要添加一个空格上去
if(left!=0) s[left++] = ' ';
//添加这个字符串直到遇到空格
while(i<s.length()&&s[i]!=' ')
{
s[left++] = s[i++];
}
}
}
//整合长度
s.resize(left);
return s;
}
public:
string reverseWords(string s) {
s = ClearSpace(s);
s = reverse(s,0,s.length()-1);
//以空格分割再翻转回来
int left = 0;
for(int i=0;i<=s.length();i++)
{
if(i==s.length() || s[i]==' ')
{
reverse(s,left,i-1);
//更新left
left = i+1;
}
}
return s;
}
};
时间复杂度
O
(
n
)
O(n)
O(n)
空间复杂度
O
(
1
)
O(1)
O(1)
右旋字符串
文档讲解:代码随想录
视频讲解:
状态:√
先整体翻转,再按照k分段翻转
//先整体翻转,再以k分割翻转
#include <iostream>
#include <string>
using namespace std;
void Reverse(string& s,int begin,int end)
{
while(begin<end)
{
swap(s[begin],s[end]);
begin++;
end--;
}
}
int main()
{
int k;
cin>>k;
string s;
cin>>s;
Reverse(s,0,s.length()-1);
Reverse(s,0,k-1);
Reverse(s,k,s.length()-1);
for(int i=0;i<s.length();i++)
{
cout << s[i];
}
return 0;
}