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.
- 1 <= s.length <= 10⁴
- s contains English letters (upper-case and lower-case), digits, and spaces ' '.
- There is at least one word in s.
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.
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.
Approach
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.
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.
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.
Reverse the word list
With clean tokens in hand, reverse the list. Every word retains its own internal character order — only their positions change.
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.
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.
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.
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.
Solution & live demo
Common pitfalls
Splitting on a literal space
words = s.split(" ")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
return s[::-1]
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
return ' '.join(reversed(s.strip().split(" ")))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.
Edge cases
split() discards them, so the output has no stray edge spaces.
Runs of spaces collapse to one because split() treats them as a single delimiter.
Reversing a one-element list returns it unchanged.