一、题目描述
给你一个字符串 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 跳过多余空格
遍历字符串时:
-
先跳过所有
' '空格 -
找到单词开始位置
例如:
" 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) 额外空间,可以采用经典三步:
-
去除多余空格
-
整体反转字符串
-
逐个单词再反转
例如:
原字符串
the sky is blue
整体反转
eulb si yks eht
逐词反转
blue is sky the
这样可以做到 原地修改字符串。
六、总结
本题是一道非常经典的 字符串处理题,重点在于:
-
跳过多余空格
-
正确识别单词边界
-
控制结果字符串的空格数量
常见做法有两种:
| 方法 | 空间复杂度 | 难度 |
|---|---|---|
| 提取单词 + 倒序拼接 | O(n) | 简单 |
| 原地三次反转 | O(1) | 中等 |
在面试中,建议优先写 提取单词版本,代码清晰不容易出错。