LeetCode #151 Medium

Reverse Words in a String

Reverse the order of words in s, collapsing extra spaces so the result has single spaces and no leading or trailing space.

Constraints
  • 1 <= s.length <= 10⁴
  • s contains English letters (upper-case and lower-case), digits, and spaces ' '.
  • There is at least one word in s.
stringtwo-pointers
Open on LeetCode ↗
02

Intuition

Reverse words in a string reverses the order of words while normalising the spacing — the output must have single spaces, no leading space, and no trailing space. The reversal is trivial; the whitespace is the actual problem. The input can have leading spaces, trailing spaces, and multiple spaces between words. Splitting naively on a single space character produces empty strings for every extra space, and those empties then appear in the output as stray spaces. Most languages provide exactly the right tool: - Splitting on runs of whitespace, rather than on a single space, discards the empties and yields clean words. In Python that is split() with no argument — deliberately different from split(" "), which keeps the empties. Java has trim().split("\\s+"). Once the words are clean, reverse the list and join with a single space, and the output constraints are satisfied automatically. The follow-up usually asked is to do it in place with O(1) space, which matters in languages where strings are mutable character arrays. The standard technique is two reversals: reverse the entire string, then reverse each word individually back to its correct orientation. Whitespace normalisation then happens with a separate two-pointer compaction pass. In Python and Java, strings are immutable, so O(1) space is not achievable regardless — worth saying rather than pretending otherwise.

How to spot this pattern

The interesting part is whitespace, not reversal. split() with no argument collapses arbitrary runs of spaces and drops leading and trailing ones in a single call — which is exactly the specification. When a language builtin already implements the messy half of the spec, using it is the answer, and knowing why it fits is the thing to be able to explain.

03

Approach

Try it first

Before reading on: price up what the direct approach costs here, then ask what you would need to remember from the left to avoid re-scanning. Aim for O(n) time and O(n) space.

1

Recognise where the difficulty is

Reversing word order is trivial. The messy spacing is the real problem — leading, trailing and repeated spaces all have to vanish from the output.

2

Split on runs of whitespace

Use split() with no argument in Python, or trim().split("\\s+") in Java. Splitting on a single space keeps empty strings for every extra space, and those become stray spaces in the result.

3

Reverse the word list

With clean tokens in hand, reverse the list. Every word retains its own internal character order — only their positions change.

4

Join with single spaces

Joining the reversed list with one space satisfies all three output constraints at once: single spacing, no leading space, no trailing space. No trimming pass is needed afterwards.

5

Know the in-place follow-up

On a mutable character array, reverse the whole string then reverse each word back, with a two-pointer pass to compact the spaces. This achieves O(1) space where the language allows it.

6

Be honest about immutable strings

In Python and Java, strings are immutable, so O(1) space is impossible regardless of technique. Saying so is better than claiming a bound the language cannot deliver.

7

Cost of the approach

Splitting, reversing and joining are each linear, giving O(n) time and O(n) space for the token list and the output string.

04

Solution & live demo

▶1class Solution:
▶2 def reverseWords(self, s):
▶3 return ' '.join(reversed(s.split()))
05

Common pitfalls

Splitting on a literal space

✗ Wrong
words = s.split(" ")
✓ Right
words = s.split()

Splitting on " " yields empty strings for every double space and for leading or trailing ones, so the joined result carries stray gaps. The no-argument form treats any run of whitespace as one separator and discards the empties.

Reversing the characters instead of the words

✗ Wrong
return s[::-1]
✓ Right
return ' '.join(reversed(s.split()))

That spells every word backwards. The unit being reversed is the word list, so the string has to be tokenised first.

Trimming manually before splitting

✗ Wrong
return ' '.join(reversed(s.strip().split(" ")))
✓ Right
return ' '.join(reversed(s.split()))

strip() only removes the outer whitespace and leaves interior double spaces producing empty tokens. The plain split() handles both cases, so the extra call adds code without fixing the real problem.

06

Edge cases

Leading/trailing spaces, e.g. ' hello world '

split() discards them, so the output has no stray edge spaces.

Multiple spaces between words

Runs of spaces collapse to one because split() treats them as a single delimiter.

Single word

Reversing a one-element list returns it unchanged.

07

Complexity

Time
O(n)
Space
O(n)
Splitting and joining build new strings proportional to the input.