LeetCode 151中等双指针/字符串
反转字符串中的单词 图解题解
这道题到底在问什么
给定字符串 s(可能有前导/尾随/连续空格),反转其中单词的顺序,单词内部字符不变,输出单词间只保留一个空格。
- 输入
- s = "the sky is blue"
- 输出
- "blue is sky the"
- 输入
- s = " hello world "
- 输出
- "world hello"(去首尾空格)
最优解:一步一步想明白
- 3记住「先拆词去空、再从末尾往前逐个拼」,下面每帧都在套它。
- 4先把原句按空格切开、丢掉所有空串,得到 6 个干净单词(多余空格全没了)。接下来确认这些单词,再从最右边往左逐个拼。
- 5第 0 个单词是 “the”(蓝色标已确认)。空格只是分隔符,连续空格不会产生空单词——这一步顺手就把空格问题解决了。
- 6第 1 个单词是 “quick”(蓝色标已确认)。空格只是分隔符,连续空格不会产生空单词——这一步顺手就把空格问题解决了。
- 7第 2 个单词是 “brown”(蓝色标已确认)。空格只是分隔符,连续空格不会产生空单词——这一步顺手就把空格问题解决了。
- 8第 3 个单词是 “fox”(蓝色标已确认)。空格只是分隔符,连续空格不会产生空单词——这一步顺手就把空格问题解决了。
- 9第 4 个单词是 “jumps”(蓝色标已确认)。空格只是分隔符,连续空格不会产生空单词——这一步顺手就把空格问题解决了。
- 10第 5 个单词是 “now”(蓝色标已确认)。空格只是分隔符,连续空格不会产生空单词——这一步顺手就把空格问题解决了。
- 11从右往左:现在轮到下标 5 的 “now”(绿色),把它取出来准备放到结果末尾。
- 12把 “now” 拼进结果,单词间只放一个空格。已放入 1 个,结果现在是 “now”。
- 13从右往左:现在轮到下标 4 的 “jumps”(绿色),把它取出来准备放到结果末尾。
- 14把 “jumps” 拼进结果,单词间只放一个空格。已放入 2 个,结果现在是 “now jumps”。
- 15从右往左:现在轮到下标 3 的 “fox”(绿色),把它取出来准备放到结果末尾。
- 16把 “fox” 拼进结果,单词间只放一个空格。已放入 3 个,结果现在是 “now jumps fox”。
- 17从右往左:现在轮到下标 2 的 “brown”(绿色),把它取出来准备放到结果末尾。
- 18把 “brown” 拼进结果,单词间只放一个空格。已放入 4 个,结果现在是 “now jumps fox brown”。
- 19从右往左:现在轮到下标 1 的 “quick”(绿色),把它取出来准备放到结果末尾。
- 20把 “quick” 拼进结果,单词间只放一个空格。已放入 5 个,结果现在是 “now jumps fox brown quick”。
- 21从右往左:现在轮到下标 0 的 “the”(绿色),把它取出来准备放到结果末尾。
- 22把 “the” 拼进结果,单词间只放一个空格。已放入 6 个,结果现在是 “now jumps fox brown quick the”。
- 23从最后一个一路拼到第一个,单词顺序就整体反过来了,单词间只留一个空格。最终答案:“now jumps fox brown quick the”。
⚠️ 容易写错的地方
✗ 错:只 trim 首尾、没处理中间连续空格
✓ 对:按「一个或多个空格」整体切,并丢掉空串
"a good example" 中间多空格会切出空串,不丢会多出空单词
✗ 错:逆序时把单词内部字符也反了
✓ 对:只反单词顺序,单词内部不动
题目要求单词内部保持原样
✗ 错:拼接时每个单词后都加空格
✓ 对:单词之间才加空格(末尾不留)
否则结果尾部会多一个空格
完整代码(Python / C++ / Java)
Python
class Solution:
def reverseWords(self, s: str) -> str:
return ' '.join(reversed(s.split()))C++
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
class Solution {
public:
string reverseWords(string s) {
stringstream ss(s);
vector<string> words;
string w;
while (ss >> w) words.push_back(w);
reverse(words.begin(), words.end());
string ans;
for (int i = 0; i < (int)words.size(); ++i) { if (i) ans += ' '; ans += words[i]; }
return ans;
}
};Java
import java.util.*;
class Solution {
public String reverseWords(String s) {
String trimmed = s.trim();
if (trimmed.isEmpty()) return "";
String[] parts = trimmed.split("\\s+");
StringBuilder sb = new StringBuilder();
for (int i = parts.length - 1; i >= 0; i--) {
if (sb.length() > 0) sb.append(' ');
sb.append(parts[i]);
}
return sb.toString();
}
}复杂度
时间
O(n)
扫一遍切词 + 逆序拼接
空间
O(n)
存切出的单词与结果串
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 反转字符串中的单词 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
能否做到 O(1) 额外空间(原地)?+
在 C++ 这类可变字符串里可以:先整体反转整个字符串,再把每个单词单独反转回来,同时原地清理多余空格(双指针压缩)。这样不额外开单词数组。Python/Java 字符串不可变,通常用 split/join 的 O(n) 空间写法,面试讲清原地思路即可。
split() 不带参数和 split(" ") 有什么区别?+
Python 的 str.split() 不带参数会按任意空白切分并自动丢弃空串,正好满足本题;而 split(" ") 按单个空格切,连续空格会切出空串,需要再手动过滤。所以这里用无参 split 最省事。
想听吴师兄把这道题讲给你听?
文字版和动画都随便看。开通图解算法年卡,可以听吴师兄声线把 反转字符串中的单词 一步步讲透(全站 0 节语音精讲,持续扩充), 卡住的地方还有 AI 私教小欧就着动画帮你拆到懂。
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。