LeetCode 151. 反转字符串中的单词(C语言)【双指针 + 字符串处理】

一、题目描述

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

  • 单词是由 非空格字符组成的字符串

  • s 中使用至少一个空格将字符串中的单词分隔开。

  • 返回 单词顺序颠倒且单词之间用单个空格连接 的结果字符串。

需要注意:

  • 输入字符串可能包含 前导空格

  • 可能包含 尾随空格

  • 单词之间可能有 多个空格

  • 结果字符串 不能包含多余空格

示例 1

复制代码
输入:s = "the sky is blue"
输出:"blue is sky the"

示例 2

复制代码
输入:s = "  hello world  "
输出:"world hello"

示例 3

复制代码
输入:s = "a good   example"
输出:"example good a"

提示

复制代码
1 <= s.length <= 10^4
s 由英文字母、数字和空格组成
s 中至少存在一个单词

二、解题思路

题目的核心要求有三个:

  1. 去除多余空格

  2. 提取每个单词

  3. 反转单词顺序

我们可以采用 字符串扫描 + 倒序拼接 的方式完成。

整体步骤如下:

1 跳过多余空格

遍历字符串时:

  • 先跳过所有 ' ' 空格

  • 找到单词开始位置

例如:

复制代码
"   hello world  "
    ^

跳过空格后指向 hello


2 提取单词

继续向后遍历直到遇到空格:

复制代码
hello
^   ^
start end

这样我们就得到了一个单词。

然后把这个单词保存起来。


3 保存所有单词

依次扫描字符串,把所有单词存入数组:

复制代码
["the", "sky", "is", "blue"]

4 倒序拼接

将数组 从后向前拼接

复制代码
blue is sky the

拼接时:

  • 单词之间加入一个空格

  • 最后一个单词后不加空格


三、代码实现(C语言)

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* reverseWords(char* s) {
    int len = strlen(s);
    
    // 存储单词指针
    char** words = (char**)malloc(sizeof(char*) * len);
    int wordCount = 0;

    int i = 0;

    while (i < len) {

        // 1 跳过空格
        while (i < len && s[i] == ' ')
            i++;

        if (i >= len)
            break;

        int start = i;

        // 2 找到单词结尾
        while (i < len && s[i] != ' ')
            i++;

        int end = i;

        // 3 提取单词
        int wordLen = end - start;
        char* word = (char*)malloc(wordLen + 1);

        strncpy(word, s + start, wordLen);
        word[wordLen] = '\0';

        words[wordCount++] = word;
    }

    // 4 计算结果长度
    int totalLen = 0;
    for (i = 0; i < wordCount; i++)
        totalLen += strlen(words[i]);

    totalLen += wordCount - 1;

    char* result = (char*)malloc(totalLen + 1);
    result[0] = '\0';

    // 5 倒序拼接
    for (i = wordCount - 1; i >= 0; i--) {
        strcat(result, words[i]);

        if (i > 0)
            strcat(result, " ");

        free(words[i]);
    }

    free(words);

    return result;
}

四、复杂度分析

时间复杂度

复制代码
O(n)
  • 遍历字符串一次

  • 拼接字符串一次

整体仍然是线性复杂度。


空间复杂度

复制代码
O(n)

需要额外数组存储单词。


五、进一步优化(进阶)

题目进阶要求 O(1) 额外空间,可以采用经典三步:

  1. 去除多余空格

  2. 整体反转字符串

  3. 逐个单词再反转

例如:

复制代码
原字符串
the sky is blue

整体反转
eulb si yks eht

逐词反转
blue is sky the

这样可以做到 原地修改字符串


六、总结

本题是一道非常经典的 字符串处理题,重点在于:

  • 跳过多余空格

  • 正确识别单词边界

  • 控制结果字符串的空格数量

常见做法有两种:

方法 空间复杂度 难度
提取单词 + 倒序拼接 O(n) 简单
原地三次反转 O(1) 中等

在面试中,建议优先写 提取单词版本,代码清晰不容易出错。


相关推荐
_olone2 小时前
牛客每日一题:刷题统计(Java)
java·算法·容斥原理·牛客
无敌憨憨大王2 小时前
DFS(深搜)
算法·深度优先·图论
junnhwan2 小时前
LeetCode Hot 100——栈
java·数据结构·算法·leetcode·hot 100
sqyno1sky2 小时前
代码动态生成技术
开发语言·c++·算法
圣保罗的大教堂2 小时前
leetcode 1727. 重新排列后的最大子矩阵 中等
leetcode
superior tigre2 小时前
347 前k个高频元素
数据结构·算法·leetcode
廖圣平2 小时前
Drogon 现代化C ++高性能框架
android·c语言·开发语言
2401_853576502 小时前
C++中的策略模式变体
开发语言·c++·算法
m0_528174452 小时前
C++中的策略模式实战
开发语言·c++·算法