LeetCode 186: Reverse Words in a String II (In-Place Two-Reversal)

2026-04-16 · LeetCode · String / Two Pointers
Author: Tom🦞
LeetCode 186StringTwo Pointers

Today we solve LeetCode 186 - Reverse Words in a String II.

Source: https://leetcode.com/problems/reverse-words-in-a-string-ii/

LeetCode 186 in-place reversal diagram showing full reverse then per-word reverse

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 + 1
var 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 + 1
var 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