LeetCode 186: Reverse Words in a String II (In-Place Two-Reversal)
LeetCode 186StringTwo PointersToday we solve LeetCode 186 - Reverse Words in a String II.
Source: https://leetcode.com/problems/reverse-words-in-a-string-ii/
English
Problem Summary
Given a character array s, reverse the order of words in-place. A word is separated by a single space, and the array does not have leading/trailing spaces.
Key Insight
Do two reversals: first reverse the entire array, then reverse each word segment individually. This keeps space usage O(1) while restoring each word's character order.
Algorithm
- Reverse the whole array s[0..n-1].
- Scan with pointer i; for each word range [i, j-1], reverse that range.
- Move to the next word after the space and continue until end.
Complexity Analysis
Time: O(n) (each character swapped a constant number of times).
Space: O(1).
Common Pitfalls
- Forgetting to reverse the last word after loop.
- Off-by-one when handling word end at the array boundary.
- Accidentally allocating a new string/array, violating in-place requirement.
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public void reverseWords(char[] s) {
reverse(s, 0, s.length - 1);
int n = s.length;
int i = 0;
while (i < n) {
int j = i;
while (j < n && s[j] != ' ') {
j++;
}
reverse(s, i, j - 1);
i = j + 1;
}
}
private void reverse(char[] s, int l, int r) {
while (l < r) {
char tmp = s[l];
s[l] = s[r];
s[r] = tmp;
l++;
r--;
}
}
}func reverseWords(s []byte) {
reverse(s, 0, len(s)-1)
n := len(s)
i := 0
for i < n {
j := i
for j < n && s[j] != ' ' {
j++
}
reverse(s, i, j-1)
i = j + 1
}
}
func reverse(s []byte, l, r int) {
for l < r {
s[l], s[r] = s[r], s[l]
l++
r--
}
}class Solution {
public:
void reverseWords(vector<char>& s) {
reverseRange(s, 0, (int)s.size() - 1);
int n = (int)s.size();
int i = 0;
while (i < n) {
int j = i;
while (j < n && s[j] != ' ') j++;
reverseRange(s, i, j - 1);
i = j + 1;
}
}
private:
void reverseRange(vector<char>& s, int l, int r) {
while (l < r) {
swap(s[l++], s[r--]);
}
}
};class Solution:
def reverseWords(self, s: List[str]) -> None:
def rev(l: int, r: int) -> None:
while l < r:
s[l], s[r] = s[r], s[l]
l += 1
r -= 1
n = len(s)
rev(0, n - 1)
i = 0
while i < n:
j = i
while j < n and s[j] != ' ':
j += 1
rev(i, j - 1)
i = j + 1var reverseWords = function(s) {
reverse(s, 0, s.length - 1);
let i = 0;
while (i < s.length) {
let j = i;
while (j < s.length && s[j] !== ' ') {
j++;
}
reverse(s, i, j - 1);
i = j + 1;
}
};
function reverse(s, l, r) {
while (l < r) {
const tmp = s[l];
s[l] = s[r];
s[r] = tmp;
l++;
r--;
}
}中文
题目概述
给你一个字符数组 s,要求原地反转单词顺序。单词之间由单个空格分隔,且没有首尾空格。
核心思路
两次反转:先整体反转数组,再逐个单词区间反转。这样最终单词顺序被反过来,同时每个单词内部字符顺序也恢复正确。
算法步骤
- 先反转区间 [0, n-1]。
- 用双指针找到每个单词区间 [i, j-1],并原地反转。
- 跳过空格继续处理下一个单词,直到结束。
复杂度分析
时间复杂度:O(n)(每个字符被交换常数次)。
空间复杂度:O(1)。
常见陷阱
- 循环结束时漏掉最后一个单词的反转。
- 单词右边界处理成 j 而不是 j - 1。
- 新建字符串导致不满足原地修改要求。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public void reverseWords(char[] s) {
reverse(s, 0, s.length - 1);
int n = s.length;
int i = 0;
while (i < n) {
int j = i;
while (j < n && s[j] != ' ') {
j++;
}
reverse(s, i, j - 1);
i = j + 1;
}
}
private void reverse(char[] s, int l, int r) {
while (l < r) {
char tmp = s[l];
s[l] = s[r];
s[r] = tmp;
l++;
r--;
}
}
}func reverseWords(s []byte) {
reverse(s, 0, len(s)-1)
n := len(s)
i := 0
for i < n {
j := i
for j < n && s[j] != ' ' {
j++
}
reverse(s, i, j-1)
i = j + 1
}
}
func reverse(s []byte, l, r int) {
for l < r {
s[l], s[r] = s[r], s[l]
l++
r--
}
}class Solution {
public:
void reverseWords(vector<char>& s) {
reverseRange(s, 0, (int)s.size() - 1);
int n = (int)s.size();
int i = 0;
while (i < n) {
int j = i;
while (j < n && s[j] != ' ') j++;
reverseRange(s, i, j - 1);
i = j + 1;
}
}
private:
void reverseRange(vector<char>& s, int l, int r) {
while (l < r) {
swap(s[l++], s[r--]);
}
}
};class Solution:
def reverseWords(self, s: List[str]) -> None:
def rev(l: int, r: int) -> None:
while l < r:
s[l], s[r] = s[r], s[l]
l += 1
r -= 1
n = len(s)
rev(0, n - 1)
i = 0
while i < n:
j = i
while j < n and s[j] != ' ':
j += 1
rev(i, j - 1)
i = j + 1var reverseWords = function(s) {
reverse(s, 0, s.length - 1);
let i = 0;
while (i < s.length) {
let j = i;
while (j < s.length && s[j] !== ' ') {
j++;
}
reverse(s, i, j - 1);
i = j + 1;
}
};
function reverse(s, l, r) {
while (l < r) {
const tmp = s[l];
s[l] = s[r];
s[r] = tmp;
l++;
r--;
}
}
Comments