#151
中等
中频
倒序扫描翻转字符串里的单词
这是一道围绕字符串展开的高频练习。建议先掌握「倒序扫描」这套写法,再结合下方步骤讲解理解状态维护、边界处理和复杂度取舍。
字符串
题目分析
这道题表面上是在处理「翻转字符串里的单词」,但先要想清楚题目到底让你返回什么,以及过程中哪些约束必须一直满足。从题型上看,它主要在考 字符串 这些能力。先别急着写代码,先把题目要求翻译成人话,明确结果是什么、约束是什么、过程里要持续维护什么。只有先把题目要求翻译成人话,后面的推荐代码才是在实现思路,而不是直接给答案。
接下来怎么看推荐代码: 带着这个理解再看推荐代码时,重点观察这条主线:从字符串末尾向前扫描,按单词边界依次截取并拼接,就能自然得到翻转后的单词顺序。
推荐代码
推荐解法:倒序扫描
时间复杂度: O(n)
空间复杂度: O(n)
核心思路: 从字符串末尾向前扫描,按单词边界依次截取并拼接,就能自然得到翻转后的单词顺序。
class Solution {
public String reverseWords(String s) {
StringBuilder builder = new StringBuilder();
int right = s.length() - 1;
while (right >= 0) {
while (right >= 0 && s.charAt(right) == ' ') {
right--;
}
if (right < 0) {
break;
}
int left = right;
while (left >= 0 && s.charAt(left) != ' ') {
left--;
}
if (builder.length() > 0) {
builder.append(' ');
}
builder.append(s, left + 1, right + 1);
right = left - 1;
}
return builder.toString();
}
}结构化讲解
面试时怎么讲
开场思路
这题我会从后往前扫描字符串,按单词粒度重组答案。
核心过程
- 先跳过末尾空格,找到一个单词的结尾。
- 继续向前找到这个单词的起点。
- 把单词追加到结果里,必要时补一个空格。
- 重复这个过程直到扫描完整个字符串。
复杂度总结
时间复杂度 O(n),空间复杂度 O(n)。
面试补一句:这题要强调翻转的是“单词顺序”,不是把整串字符倒过来。
核心思路
题目要翻转的是单词顺序,不是字符顺序。最直接的办法是从后往前找每个单词,跳过多余空格并按顺序追加到结果里。
步骤讲解
1
从后往前跳过空格
先把尾部连续空格全部略过,定位到一个单词的结尾。
为什么这样做:题目要求结果中单词之间只保留一个空格。
对应代码提示:while (right >= 0 && s.charAt(right) == ' ') right--;
2
找到当前单词边界
继续向前移动直到遇到空格,得到当前单词的起止位置。
为什么这样做:这样可以原样截取单词,不会打乱字符内部顺序。
对应代码提示:builder.append(s, left + 1, right + 1);
3
按需插入分隔空格
只有结果里已经有内容时,才在下一个单词前补空格。
为什么这样做:避免开头或结尾出现多余空格。
对应代码提示:if (builder.length() > 0) builder.append(' ');
易错点
先 `split(" ")` 再处理空串
虽然能做,但要额外过滤大量空串,不够稳。
正确理解:直接双指针扫描原串,逻辑更可控。
单词之间拼接出多个空格
如果每次都先追加空格,结果格式会错。
正确理解:只在结果非空时追加一个空格。
复杂度与适用判断
时间复杂度:O(n)
空间复杂度:O(n)
比其他方案更好在哪里:比先拆分数组再反转更节省中间对象,也更贴近题意。
适用判断:处理字符串里连续分隔符、且结果要规整化时,双指针扫描很合适。
额外提醒
- 先跳空格,再抓单词,是这题最稳定的扫描节奏。