(写给未来遗忘的自己)
class Solution {
public:
string reverseWords(string s) {
int fast_ptr = 0;
int slow_ptr = 0;
while (fast_ptr < s.size()) {
if (s[fast_ptr] != ' ') {
s[slow_ptr] = s[fast_ptr];
slow_ptr++;
}
if (slow_ptr != 0 && s[fast_ptr] == ' ' && s[fast_ptr - 1] != ' ') {
s[slow_ptr] = ' ';
slow_ptr++;
}
fast_ptr++;
}
if (slow_ptr > 0 && s[slow_ptr - 1] == ' ') {
slow_ptr--;
}
string s_input = s.substr(0, slow_ptr);
reverse(s_input.begin(), s_input.end());
int start = 0;
for (int end = 0; end <= s_input.size(); end++) {
if (end == s_input.size() || s_input[end] == ' ') {
reverse(s_input.begin() + start, s_input.begin() + end);
start = end + 1;
}
}
return s_input;
}
};
思路:
1.将所有多余的空格删除掉(开头的空格,中间超过两个的空格,结尾的空格)
利用快慢指针,快指针遍历旧数组,慢指针维护删除多余空格的新数组(新旧数组是一个,新数组是前面的slow_ptr项)。
快指针起到遍历的作用,快指针的值影响慢指针的赋值。
快指针不是空,就把快指针的值复制一份给慢指针的位置,慢指针+1,快指针继续遍历;
快指针是空且前一个值不是空(非开头),说明是必要的空格,就给慢指针赋值一个空,然后慢指针+1,快指针继续遍历。
int fast_ptr = 0;
int slow_ptr = 0;
while (fast_ptr < s.size()) {
if (s[fast_ptr] != ' ') {
s[slow_ptr] = s[fast_ptr];
slow_ptr++;
}
if (slow_ptr != 0 && s[fast_ptr] == ' ' && s[fast_ptr - 1] != ' ') {
s[slow_ptr] = ' ';
slow_ptr++;
}
fast_ptr++;
}
由于是先给慢指针赋值再加一,所以跳出循环时候的时候,慢指针是新数组的大小,不是下标。
if (slow_ptr > 0 && s[slow_ptr - 1] == ' ') {
slow_ptr--;
}
string s_input = s.substr(0, slow_ptr);
reverse(s_input.begin(), s_input.end());
2.利用reverse()将整个数组反转
3.继续将单个单词反转
这个注意上一个文章中说的,reverse()是一个左闭右开的范围就可以。所以循环的范围要到达下标的下一个作为end。
在其他地方是以空格为end,在结尾的时候需要以最后一个下标的下一个(也就是数组大小)为界。
for (int end = 0; end <= s_input.size(); end++) {
if (end == s_input.size() || s_input[end] == ' ') {
reverse(s_input.begin() + start, s_input.begin() + end);
start = end + 1;
}
}
补充知识:std::string
类修改大小的方法
1.使用 resize
方法:
resize
方法可以改变字符串的长度。如果新长度大于当前长度,它会在字符串末尾添加空字符(默认行为),或者你可以指定一个字符来填充。- 如果新长度小于当前长度,它会截断字符串。
#include <iostream>
#include <string>
int main() {
std::string s = "Hello, World!";
s.resize(5); // 将字符串裁剪到5个字符
std::cout << s << std::endl;
s = "Hello, World!";
s.resize(10, 'x'); // 将字符串扩展到10个字符,不足部分用'x'填充
std::cout << s << std::endl;
return 0;
}
2.使用 substr
方法:
substr
方法可以返回一个子字符串,但不会改变原始字符串。你可以将返回的子字符串赋值给另一个字符串变量。
#include <iostream>
#include <string>
int main() {
std::string s = "Hello, World!";
std::string sub = s.substr(0, 5); // 获取前5个字符
std::cout << sub << std::endl;
return 0;
}
3.使用 erase
方法:
erase
方法可以用来删除字符串中的某些字符。你可以指定删除的起始位置和删除的字符数。
#include <iostream>
#include <string>
int main() {
std::string s = "Hello, World!";
s.erase(7, 6); // 从第7个字符开始删除6个字符
std::cout << s << std::endl;
return 0;
}
4.使用 append
或 +=
操作符:
- 这些方法可以向字符串末尾添加字符或另一个字符串。
#include <iostream>
#include <string>
int main() {
std::string s = "Hello";
s += ", World!"; // 向字符串末尾添加", World!"
std::cout << s << std::endl;
return 0;
}
5.使用 replace
方法:
replace
方法可以用来替换字符串中的某些字符。
#include <iostream>
#include <string>
int main() {
std::string s = "Hello, World!";
s.replace(7, 6, "there"); // 从第7个字符开始替换6个字符为"there"
std::cout << s << std::endl;
return 0;
}