c++代码(双指针)------------->(编写reserve函数)
class Solution {
public:
void reverseString(vector& s) {
int t = s.size();
for (int i = 0, j = t - 1 ; i < j; i++,j--) {//双指针
swap(s[i],s[j]);
}
}
};
思路
前后双指针不断靠近中间,交换两边的数据,就可以完成交换,这道题和“有序数组的平方差不多”,都是两边指针,
c++代码
class Solution {
public:
string reverseStr(string s, int k) {
int t = s.size();
int i = 0;
for (i = 0; i < t; i += 2*k) {//减少代码量
// 1. 每隔 2k 个字符的前 k 个字符进行反转
// 2. 剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符
if (i + k <= t) {
reverse(s.begin()+i, s.begin() + k + i);
} else {
// 3. 剩余字符少于 k 个,则将剩余字符全部反转。
reverse(s.begin()+i, s.end());//左闭右开
}
}
return s;
}
};
思路
每次移动2*k步,移动前提前判断,如果可以过k步,就翻转k个,如果不够,翻转后面的全部
所以当需要固定规律一段一段去处理字符串的时候,要想想在在for循环的表达式上做做文章
为什么可以用库函数呢,因为不是关键解题步骤。
c++代码(双指针)
class Solution {
public:
string replaceSpace(string s) {
int count = 0;
int ordlen = s.size();
for (int i = 0; i < ordlen; i++) {
if (s[i]== ' ') count++;//计算空格数量
}
s.resize(ordlen + 2 * count);//申请空间
int newlen = s.size();
int i = newlen;
for (int j = ordlen; j >= 0; j--) {
if (s[j] != ' ') {//不为空格,就直接覆盖
s[i] = s[j];
i--;
} else {为空格就填充%20
s[i] = '0';
s[i - 1] = '2';
s[i - 2] = '%';
i -= 3;
}
}
return s;
}
};
思路
计算空格个数,根据需要加东西申请空间,一个指针在原来位置后面,一个指针在在现在位置最后面,第一个指针不断往前推,如果不是空格就加入新字符串最后,如果是,就加入%20再进行遍历,相当于往前推三个位置
问题:为什么要从后向前填充,从前向后填充不行么?
从前向后填充每次填充都会向后移动后面的元素,就会变成O(n*2)的时间复杂度了
官方讲解---代码随想录
c++代码
class Solution {
public:
//移除空格 并 在每个单词中加入 空格
void removeExtraSpaces(string& s) {
int slow = 0;
for (int fast = 0; fast < s.size(); ++fast) {//外层循环进行判断空格,直到找到单词位置
if (s[fast] != ' ') {//找到单词位置
if(slow != 0 ) s[slow++] = ' ';//如果第一次找到单词位置 就不用加空格,否则前面就有单词,说明要加入空格
while(s[fast] != ' ' && fast < s.size()) {//补上该单词,遇到空格说明单词结束。
s[slow++] = s[fast++];
// fast++;
// slow++;
}
}
}
s.resize(slow);
}
//翻转全局位置再翻转局部位置
string reverseWords(string s) {
removeExtraSpaces(s);
int len = s.size();
reverse(s.begin(), s.begin() + len);//翻转全局位置
int res = 0;
for (int i = 0; i <=len; i++) {
if (i == len || s[i] == ' ') { //下一个是空格或则到末尾都可以
reverse(s.begin() + res, s.begin() + i);//左闭右开
res = i + 1;
}
}
return s;
}
};
思路
只要理解怎么移除空格就可以差不多写出这道题目,,这部分和27.移除元素 (opens new window)的逻辑是一样一样的,本题是移除空格,而 27.移除元素 就是移除元素。
步骤:
所以这里我还是提高一下本题的难度:不要使用辅助空间,空间复杂度要求为O(1)。
怎么完成第一步,删除并添加空格
可以看下图:
反转最后一个单词
就不能判断后面是否为空格了,需要判断是否到达了最后
c++代码
class Solution {
public:
string reverseLeftWords(string s, int n) {
reverse(s.begin(), s.end());//e.end()返回最后一个元素下一个元素的下标
reverse(s.begin(), s.begin() + s.size() - n);
reverse(s.begin() + s.size() - n , s.end());
return s;
}
};
步骤:
为了让本题更有意义,提升一下本题难度:不能申请额外空间,只能在本串上操作。那么我们可以想一下上一题目字符串:花式反转还不够! (opens new window)中讲过,使用整体反转+局部反转就可以实现反转单词顺序的目的。依然可以通过局部反转+整体反转 达到左旋转的目的。
在这篇文章344.反转字符串 (opens new window),第一次讲到反转一个字符串应该怎么做,使用了双指针法。
然后发现541. 反转字符串II (opens new window),这里开始给反转加上了一些条件,当需要固定规律一段一段去处理字符串的时候,要想想在for循环的表达式上做做文章。
后来在151.翻转字符串里的单词 (opens new window)中,要对一句话里的单词顺序进行反转,发现先整体反转再局部反转 是一个很妙的思路。
最后再讲到本题,本题则是先局部反转再 整体反转,与151.翻转字符串里的单词 (opens new window)类似,但是也是一种新的思路。