概述
- 这几题都和字符串翻转有关
分析
344
-
题目要求原地修改,可以考虑使用双指针+swap()函数实现
实际上,内置函数reverse()就是通过这个实现;
541
- 这题,我们利用
reverse()
模拟一下操作即可
151
- 个人认为这是一个技巧题,要能想到使用多次反转的思路
- 首先翻转整个字符串
- 然后在对每个单词进行一次翻转,即可实现最终效果
这里有一个难点在于,第二次翻转如何确定一个单词进行翻转
**剑指 Offer 58 **
- 这题,个人认为也算一个技巧题,和151一样,使用多次翻转的思路
思路
151
第二次翻转如何确定一个单词?
- 我们容易想到利用空格来区分单词,但是根据题目说明:存在前导空格、尾随空格和单词间多个空格,所以这里还是需要仔细处理一下
- 首先我们第一翻转后,题目中的三种特殊空格情况仍然存在,我们可以分情况处理:
- 对于前导空格和单词间的多个空格,我们可以每次确定一个字母后,再去寻找该字母所在的单词
- 而通常也是利用空格来区分单词。但是考虑到末尾可能不存在空格,就无法区分最后一个单词,于是为了统一操作,我们可以在末尾手动添加一个空格
代码
344
class Solution {
public:
void reverseString(vector<char>& s) {
int left = 0, right = s.size() - 1; // 双指针
while (left < right) {
swap(s[left++], s[right--]); // STL swap()
}
}
};
541
class Solution {
public:
string reverseStr(string s, int k) {
for (int i = 0; i < s.size();i += (2 * k)) { // 模拟操作
if (i + k <= s.size()) {
reverse(s.begin() + i, s.begin() + i + k );
continue;
}
reverse(s.begin() + i, s.begin() + s.size());
}
return s;
}
};
151
class Solution {
public:
string reverseWords(string s) {
reverse(s.begin(), s.end()); // 先翻转所有字符
s.push_back(' '); // 统一操作,在末尾添加空格
for(int i = 0; i < s.size(); ++i) {
if (s[i] != ' ') { // 直到出现第一个字母,可以处理前导空格和单词间多个空格
int j = i + 1;
for (; j < s.size(); ++j) {
if (s[j] == ' ') { // 遇到一个空格,可以确定该单词的前后位置索引了
reverse(s.begin() + i, s.begin() + j); // 再翻转单个单词
i = j; // 继续处理
break;
}
}
}
}
// 去除多余空格。利用双指针法,向前移动
int i = 0, j = 0;
for(;j < s.size(); ++j) {
if (s[j] != ' ')
s[i++] = s[j];
else if(s[j] == ' ' && i > 0 && s[i - 1] != ' ')
s[i++] = ' ';
}
s.resize(i - 1); // 缩小string,留下实际有用的部分
return s;
}
};
小技巧:
直接利用
resize()
来删除末尾的内存
剑指 Offer 58
class Solution {
public:
string reverseLeftWords(string s, int n) {
reverse(s.begin(), s.end()); // 第一次翻转整个字符串
int size = s.size();
// 下面两个翻转是为了恢复正常的顺序,如果不懂可以手动模拟一下
reverse(s.begin(), s.begin() + size - n);
reverse(s.begin() + size - n, s.end());
return s;
}
};