题目描述:原地反转字符串s
视频讲解https://www.bilibili.com/video/BV1fV4y17748/?spm_id_from=333.788&vd_source=f98f2942b3c4cafea8907a325fc56a48文章讲解
https://programmercarl.com/0344.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
- 思路:
- 双指针:i 从左到右,j 从右到左
- 交换 s[i] 和 s[j]
- i < j:若为奇数个,中间剩一个恰好不用操作
- 代码:
class Solution {
public:
void reverseString(vector<char>& s) {
for (int i = 0, j = s.size() - 1; i < j; ++i, --j) {
swap(s[i], s[j]);
}
}
};
题目描述:给定字符串s和整数k,反转每2k个字符的前k个。
剩余字符不足2k个,则反转前k个;不足k个,则全部反转。
视频讲解https://www.bilibili.com/video/BV1dT411j7NN/?spm_id_from=333.788&vd_source=f98f2942b3c4cafea8907a325fc56a48文章讲解
https://programmercarl.com/0541.%E5%8F%8D%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2II.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
- 思路:
- 用 i 扫描字符串 s,一次走 2k 步
- 够 k 个,反转 [i, i + k)
- 不够 k 个,反转 [i, s.size())
- 代码:
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;
}
// 剩余字符不足k个,全部反转
reverse(s.begin() + i, s.end());
}
return s;
}
};
题目描述:把字符串
s
中的每个空格替换成"%20"
- 思路:
- 统计空格数,扩充
- 双指针:i 扫新字符串,j 扫原字符串,从后往前赋值
- i 追上 j,则空格均已替换
- 代码:
class Solution {
public:
string replaceSpace(string s) {
int sOldSize = s.size();
// 统计空格数
int count = 0;
for (int i = 0; i < sOldSize; ++i) {
if (s[i] == ' ') {
++count;
}
}
// 扩充字符串
s.resize(sOldSize + count * 2);
int sNewSize = s.size();
for (int i = sNewSize - 1, j = sOldSize - 1; j < i; --i, --j) {
if (s[j] != ' ') {
s[i] = s[j];
} else {
s[i] = '0';
s[i - 1] = '2';
s[i - 2] = '%';
i -= 2;
}
}
return s;
}
};
题目描述:反转字符串s中 单词 的顺序。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。
返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。
视频讲解https://www.bilibili.com/video/BV1uT41177fX文章讲解
https://programmercarl.com/0151.%E7%BF%BB%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
- 思路: " the sky is blue "
- 删除多余空格: "the sky is blue"
- 双指针:fast 扫描原串,slow 作为新串下标
- fast 寻找非空格元素(每个单词的首字母)
- 找到后先给 slow 放置空格(第一个单词除外)
- 再移动整个单词,直到遇到空格,进入下一轮循环
- 反转整个字符串: "eulb si yks eht"
- 反转每个单词: "blue is sky the"
- 删除多余空格: "the sky is blue"
- 代码:
class Solution {
public:
// 删除多余空格
void removeExtraSpaces(string& s) {
// 双指针
// slow作为新串下标
int slow = 0;
// fast扫描原串,寻找需要移到新串的字符
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);
}
string reverseWords(string s) {
// 删除多余空格
removeExtraSpaces(s);
// 反转整个字符串
reverse(s.begin(), s.end());
// 反转每个单词
int start = 0;
for (int i = 0; i <= s.size(); ++i) {
// i扫到单词结束位置
if (i == s.size() || s[i] == ' ') {
// 反转[start, i)
reverse(s.begin() + start, s.begin() + i);
// 更新start至下一个单词的起始位置
start = i + 1;
}
}
return s;
}
};
题目描述:把字符串前面的若干个字符转移到字符串的尾部。
- 思路:
- 反转 [0, n)
- 反转 [n, s.size())
- 反转 整个字符串
- 代码:
class Solution {
public:
string reverseLeftWords(string s, int n) {
// 原地操作
// 反转 [0 , n)
reverse(s.begin(), s.begin() + n);
// 反转 [n, s.size())
reverse(s.begin() + n, s.end());
// 反转整个字符串
reverse(s.begin(), s.end());
return s;
}
};