算法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

posted on 2025-05-01 19:33  sakura430  阅读(15)  评论(0)    收藏  举报