算法day24 反转字符串中的单词
题目描述

思路一:双指针
采用双指针的思路,既然是要将单词倒置,那我们索性可以设置两个指针在初始时指向串的尾部,在左指针大于等于0的情况下,我们从右侧不断的重复先过滤空字符后采集单词的操作,最后将采集的新的串返回即可。
代码如下:
string reverseWords(string s) {
vector<char> res;
int left = s.size()-1;
int right = s.size()-1;
int begin,end;
while(left>=0){ //left的边界是大于等于0,这样才能全部遍历,不丢数据
while(left>=0 && s[left] == ' '){//这里的判断一定是要先判断left的值,否则在后续的操作下会导致越界操作
left--;
right--;
}
if(left<0) break; //若left小于0,那后续就没有操作的必要了,直接结束外层循环
while( left>=0&&s[left]!=' ') left--;
begin = left+1; //确定收集单词的开头
end = right; //结尾
while(begin<=end){
res.push_back(s[begin++]);
}
res.push_back(' ');
right = left;
}
if(!res.empty()) res.pop_back();//最后要把多余的空字符干掉,但要注意如果本身就是空的,这里会存在越界操作
return string(res.begin(),res.end());
}
时间复杂度:O(n)
空间复杂度:O(n)
思路二:双指针(空间效率优化版)
依旧采用双指针的思路,不过我们这一次并不外借空间,而是原地改变串,大体思路即正向原地移除元素,形成一个题目要求的干掉多余空格的还未逆置的半成品串,最后再逆置一下即可。
代码如下:
void reverse(string &s) { // 按引用传递
int left = 0;
int right = s.size()-1;
while(left<right){
swap(s[left++],s[right--]);
}
left = 0;
right = 0;
while (right < s.size()) {
// 找到单词右边界
while (right < s.size() && s[right] != ' ') {
right++;
}
// 反转单词 [left, right-1]
int begin = left;
int end = right - 1;
while (begin < end) {
swap(s[begin], s[end]);
begin++;
end--;
}
// 跳过空格,定位到下一个单词开头
left = right + 1;
right = left;
}
}
string reverseWords(string s) {
// 去除多余空格
int slow = 0;
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++];
}
} else {
fast++; // 仅在遇到空格时递增 fast
}
}
s.resize(slow); // 截断多余字符
reverse(s); // 反转每个单词
return s;
}
时间复杂度:O(n)
空间复杂度:O(1)
END
浙公网安备 33010602011771号