leetcode算法(151.反转字符串中的单词)

cpp 复制代码
for (int i = 0; i < s.size(); ++i) {
    if (s[i] != ' ') {                     // 第1步:发现单词开始
        if (slow != 0) s[slow++] = ' ';    // 第2步:如果需要,先加空格(此时不会重复加)
        // 第3步:复制整个单词
        while (i < s.size() && s[i] != ' ') {
            s[slow++] = s[i++];            // 注意:这里 i 也在增加!
        }
    }
    // for循环的 ++i 会执行,但此时 i 可能已经超过边界或指向空格
}
复制代码
初始状态: s = " h e l l o     w o r l  d"
               0 1 2 3 4 5 6 7 8 9 10 11
         i = 0, slow = 0, s[0] = 'h'(非空格)
执行步骤:
1. if (s[0] != ' ') 成立
2. if (slow != 0) → slow=0,所以不执行(不添加空格)
3. 进入 while 循环:
   第1轮:i=0, s[0]='h' → s[0]=s[0], slow=1, i=1
   第2轮:i=1, s[1]='e' → s[1]=s[1], slow=2, i=2
   第3轮:i=2, s[2]='l' → s[2]=s[2], slow=3, i=3
   第4轮:i=3, s[3]='l' → s[3]=s[3], slow=4, i=4
   第5轮:i=4, s[4]='o' → s[4]=s[4], slow=5, i=5
   
   第6轮:i=5, s[5]=' '(空格)→ while 条件不成立,退出循环

此时:i=5(指向空格),slow=5
for循环的 ++i 执行 → i=6

关键点:

  • while循环中的 s[slow++] = s[i++]islow 同步前进

  • 当遇到空格时,while循环立即停止,此时 i 已经指向空格位置

  • 然后 for 循环的 ++ii 指向下一个字符

cpp 复制代码
void resize(size_t n);            // 基本形式

resize() 是 C++ 标准库中 std::string 类的一个成员函数,用于改变字符串的长度。

  • n :新的字符串长度(size_t 类型,即无符号整数)

  • 如果不resize,原字符串后面可能还有多余的空格字符

  • 后续的reverse操作会操作到这些无效字符,导致错误结果

cpp 复制代码
//举例
string s = "hello world";
s.resize(5);  // s 变成 "hello"
// 索引 5 及之后的字符被丢弃
cpp 复制代码
class Solution {
public:
    // 翻转字符串中指定区间的字符 [start, end] 闭区间
    void reverse(string& s, int start, int end) {
        // 使用双指针从两端向中间交换字符
        for (int i = start, j = end; i < j; i++, j--) {
            swap(s[i], s[j]);  // 交换 s[i] 和 s[j] 位置的字符
        }
    }

    // 去除字符串中多余的空格(移除前后及中间多余空格,只保留单词间一个空格)
    void removeExtraSpaces(string& s) {
        int slow = 0;  // 慢指针,指向当前处理后字符串应存放的位置
        for (int i = 0; i < s.size(); ++i) {  // i 为快指针,遍历原字符串
            if (s[i] != ' ') {  // 遇到非空格字符(即单词部分)
                if (slow != 0) s[slow++] = ' ';  // 如果不是第一个单词,先加一个空格分隔
                // 将当前单词完整拷贝到慢指针位置
                while (i < s.size() && s[i] != ' ') {
                    s[slow++] = s[i++];
                }
            }
            // 遇到空格则跳过,由上面的 if 条件处理
        }
        s.resize(slow);  // 调整字符串大小,去除多余部分
    }

    // 主函数:反转字符串中的单词顺序
    string reverseWords(string s) {
        // 第一步:去除多余空格,规范单词间隔
        removeExtraSpaces(s); 
        // 第二步:翻转整个字符串
        reverse(s, 0, s.size() - 1);
        // 第三步:逐个单词翻转回来,恢复单词内部顺序
        int start = 0;  // 记录当前单词的起始位置
        for (int i = 0; i <= s.size(); ++i) {
            // 遇到空格或字符串结尾,说明一个单词结束
            if (i == s.size() || s[i] == ' ') {
                reverse(s, start, i - 1);  // 翻转当前单词
                start = i + 1;  // 更新下一个单词起始位置(跳过空格)
            }
        }
        return s;  // 返回处理后的字符串
    }
};
相关推荐
tobias.b16 小时前
408真题解析-2010-6-数据结构-哈夫曼树
数据结构·计算机考研·408真题解析
tobias.b17 小时前
408真题解析-2010-7-数据结构-无向连通图
数据结构·算法·图论·计算机考研·408真题解析
良木生香18 小时前
【鼠鼠优选算法-双指针】003:快乐数 & 004:盛水最多的容器
算法
Cx330❀18 小时前
【优选算法必刷100题】第41-42题(模拟):Z 字形变换,外观数列
c++·算法
沃尔特。18 小时前
直流无刷电机FOC控制算法
c语言·stm32·嵌入式硬件·算法
CW32生态社区18 小时前
CW32L012的PID温度控制——算法基础
单片机·嵌入式硬件·算法·pid·cw32
Cx330❀18 小时前
【优选算法必刷100题】第038题(位运算):消失的两个数字
开发语言·c++·算法·leetcode·面试
漫随流水18 小时前
leetcode回溯算法(93.复原IP地址)
数据结构·算法·leetcode·回溯算法
燃于AC之乐18 小时前
我的算法修炼之路--5——专破“思维陷阱”,那些让你拍案叫绝的非常规秒解
c++·算法·贪心算法·bfs·二分答案·扩展域并查集·动态规划(最长上升子序列)
艾莉丝努力练剑18 小时前
【优选算法必刷100题】第021~22题(二分查找算法):山脉数组的峰顶索引、寻找峰值
数据结构·c++·算法·leetcode·stl