字符串反转相关题目
力扣189.旋转数组(直接点击即可跳转题目)
思路分析
- 举个栗子,如果要k=15,size也是7,那么k%size=1,实际就是旋转了两个周期,然后右旋转一次,所以就是 7 1 2 3 4 5 6 ,那么我们直接reverse三次问题就解决了
代码实现
class Solution {
public:
void rotate(vector<int>& nums, int k)
{
k=k%nums.size();
reverse(nums.begin(),nums.end());
reverse(nums.begin(),nums.begin()+k);
reverse(nums.begin()+k,nums.end());
}
};
力扣344.反转字符串
思路分析
- 双指针过
代码实现
class Solution {
public:
void reverseString(vector<char>& s)
{
int l=0,r=s.size()-1;
for(;l<r;l++,r--)
swap(s[l],s[r]);
}
};
力扣541.反转字符串Ⅱ
思路分析
- 刚开始思路想着就暴力解法,后来看了题解,就用了题解的方法
- 我们可以将2k作为一段字符进行操作,就会存在以下两种情况
- 首先是
[ k ]≤字符长度<[ 2k ]
,这种情况就反转前k个字符 - 第二种情况是
字符少于k个
,这种情况就直接反转全部
代码实现
class Solution {
public:
string reverseStr(string s, int k)
{
for(int i=0;i<s.size();i+=2*k)
{
if(i+k<s.size())
{
//反转前k个
reverse(s.begin()+i,s.begin()+i+k);
}
else
{
//反转全部
reverse(s.begin()+i,s.begin()+s.size());
}
}
return s;
}
};
力扣151.翻转字符串里的单词(字节题库)
思路分析
-
看完题目初步思路是:
-
1.先把整个字符串反转 2.再翻转局部的字符串 3.再去处理多余空格
-
但是实现了半天也没有结果,还是看了题解,大概明白了两种比较好理解的方法
-
第一种就是O(n)解法
-
第二种是O(1)解法,函数全部自己实现
代码实现
O(n)
- 我们从后往前地添加单词(包括标点符号)进 res
- 每添加完一个单词,我们就给 res 手动加上一个空格
- 最后返回 res 即可
class Solution {
public:
string reverseWords(string s) {
int len = s.length();
if (len == 0) {
return "";
}
int j = len - 1;
string res = "";
while (j >= 0) {
if (s[j] == ' ') {
// 当 s[j] 是空格时,j 不断左移
j--;
continue;
}
while (j >= 0 && s[j] != ' ') {
// 注意 while 里必须用 && 短路求值,且 j >= 0 要放前面
// 不然如果 j 变成 -1,那么计算 s[j] 会发生溢出错误!
j--;
}
int pos = j; // 用 pos 保存 j 当前的位置
j++; // j 现在指向的是一个空格,需要右移一位才能指向一个单词的开头
while (s[j] != ' ' && j < len) {
// 向 res 中添加单词
res += s[j];
j++;
}
j = pos; // j 回到新添加的单词的最左端再往左一个空格处
res += ' '; // 单词添加完毕后需要加上一个空格
}
if (res[res.length() - 1] == ' ') {
// 删除 res 最后一位的多余空格
res.erase(res.length() - 1, 1);
}
return res;
}
};
O(1)
这里代码贴的是一道题解的(戳这里)
class Solution {
public:
// 反转字符串s中左闭又闭的区间[start, end]
void reverse(string& s, int start, int end)
{
for (int i = start, j = end; i < j; i++, j--)
{
swap(s[i], s[j]);
}
}
// 移除冗余空格:使用双指针(快慢指针法)O(n)的算法
void removeExtraSpaces(string& s)
{
int slowIndex = 0, fastIndex = 0; // 定义快指针,慢指针
// 去掉字符串前面的空格
while (s.size() > 0 && fastIndex < s.size() && s[fastIndex] == ' ')
{
fastIndex++;
}
for (; fastIndex < s.size(); fastIndex++)
{
// 去掉字符串中间部分的冗余空格
if (fastIndex - 1 > 0
&& s[fastIndex - 1] == s[fastIndex]
&& s[fastIndex] == ' ')
{
continue;
}
else
{
s[slowIndex++] = s[fastIndex];
}
}
if (slowIndex - 1 > 0 && s[slowIndex - 1] == ' ') { // 去掉字符串末尾的空格
s.resize(slowIndex - 1);
} else {
s.resize(slowIndex); // 重新设置字符串大小
}
}
string reverseWords(string s)
{
removeExtraSpaces(s); // 去掉冗余空格
reverse(s, 0, s.size() - 1); // 将字符串全部反转
int start = 0; // 反转的单词在字符串里起始位置
int end = 0; // 反转的单词在字符串里终止位置
bool entry = false; // 标记枚举字符串的过程中是否已经进入了单词区间
for (int i = 0; i < s.size(); i++)
{ // 开始反转单词
if ((!entry) || (s[i] != ' ' && s[i - 1] == ' '))
{
start = i; // 确定单词起始位置
entry = true; // 进入单词区间
}
// 单词后面有空格的情况,空格就是分词符
if (entry && s[i] == ' ' && s[i - 1] != ' ')
{
end = i - 1; // 确定单词终止位置
entry = false; // 结束单词区间
reverse(s, start, end);
}
// 最后一个结尾单词之后没有空格的情况
if (entry && (i == (s.size() - 1)) && s[i] != ' ' )
{
end = i;// 确定单词终止位置
entry = false; // 结束单词区间
reverse(s, start, end);
}
}
return s;
}
};
剑指offer58-Ⅱ.左旋转字符串(字节题库)
思路分析
- 我们先把 abcdefg 字符串分为两部分
- part1:ab part2:cdefg
- 分别reverse part1 和 part2
- 得到 part3:bagfedc
- reverse part3得到cdefgab
代码实现
class Solution {
public:
string reverseLeftWords(string s, int n)
{
reverse(s.begin(),s.begin()+n);
reverse(s.begin()+n,s.end());
reverse(s.begin(),s.end());
return s;
}
};