1. 问题背景与核心需求
这道LeetCode 151题要求我们反转字符串中的单词顺序,同时需要处理多余空格。举个例子,输入字符串" hello world "应该输出"world hello"。看似简单,但实际处理时需要同时考虑多种边界情况:
- 前导/后置空格处理
- 单词间多余空格压缩
- 标点符号与单词的粘连
- 字符串全为空格的特殊情况
在ACM竞赛和面试场景中,这类字符串处理题目考察的是对边界条件的敏感度和空间复杂度控制能力。我见过不少候选人能写出基本功能,却在连续空格或全空格用例上翻车。
2. 双指针法实现解析
2.1 算法思路拆解
最优解采用三次反转的经典套路:
- 移除多余空格(快慢指针)
- 反转整个字符串
- 逐个反转单词
这种做法的优势在于:
- 时间复杂度O(n)
- 空间复杂度O(1)(原地修改)
- 避免使用语言内置的split()等函数
2.2 关键代码实现
python复制def reverseWords(s: str) -> str:
def trim_spaces(s):
left, right = 0, len(s) - 1
# 去除首尾空格
while left <= right and s[left] == ' ':
left += 1
while left <= right and s[right] == ' ':
right -= 1
# 去除中间多余空格
output = []
while left <= right:
if s[left] != ' ':
output.append(s[left])
elif output[-1] != ' ':
output.append(s[left])
left += 1
return output
def reverse(l, left, right):
while left < right:
l[left], l[right] = l[right], l[left]
left += 1
right -= 1
def reverse_each_word(l):
n = len(l)
start = end = 0
while start < n:
while end < n and l[end] != ' ':
end += 1
reverse(l, start, end - 1)
start = end + 1
end += 1
l = trim_spaces(s)
reverse(l, 0, len(l) - 1)
reverse_each_word(l)
return ''.join(l)
2.3 边界条件处理
特别注意这些case:
- 全空格字符串应返回""
- 单词间多个空格要压缩为单个
- 字符串首尾可能有空格
- 单个单词不需要反转
3. 复杂度分析与优化
3.1 时间复杂度
三次线性遍历:
- 去空格O(n)
- 整体反转O(n)
- 单词反转O(n)
总时间复杂度保持O(n)
3.2 空间优化
相比直接使用split()的O(n)空间复杂度,双指针法通过原地修改将空间复杂度降至O(1)(不考虑语言字符串不可变特性)
4. 同类问题扩展
掌握这个解法后,可以解决以下变种题:
-
- 反转字符串中的单词 III
-
- 翻转字符串里的单词 II
-
- 反转字符串
这类问题的核心在于理解双指针操作字符串的范式,建议用这个模板反复练习直到形成肌肉记忆。我在面试候选人时,能流畅写出这个解法的一般都会给高分。
