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) 中等

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


相关推荐
数据皮皮侠5 分钟前
全国消协智慧 315 平台投诉信息数据库
大数据·人工智能·算法·百度·制造
8Qi814 分钟前
LeetCode 115 & 392:不同子序列 / 判断子序列
算法·leetcode·职场和发展·动态规划
小蒋学算法33 分钟前
算法-乘法表中第K小的数-二分
数据结构·算法
智者知已应修善业42 分钟前
【51单片机8个LED,已经使用了D1D2,怎么样在不动D1D2的前提下实现D6~D8的流水灯】2024-1-19
c++·经验分享·笔记·算法·51单片机
Evand J43 分钟前
【MATLAB例程】自适应渐消扩展卡尔曼滤波(AFEKF)三维雷达目标跟踪|效果已调优,附下载链接和运行结果,代码直接运行即可
开发语言·算法·matlab·目标跟踪·卡尔曼滤波·自适应滤波·代码定制
圣保罗的大教堂1 小时前
leetcode 2161. 根据给定数字划分数组 中等
leetcode
插件开发1 小时前
矢量路径运算如何选GPU技术?——适用算法对比及OpenGL/Direct3D/CUDA选型指南
算法·3d
c++之路2 小时前
C/C++ 全链路编译工具汇总
c语言·开发语言·c++
8Qi82 小时前
LeetCode 72:编辑距离(Edit Distance)—— 题解
算法·leetcode·职场和发展·动态规划
SoftLipaRZC2 小时前
顺序表的应用:通讯录项目与经典算法实战
算法