Problem
Given a string that may contain leading/trailing spaces and multiple consecutive spaces between words, return the words in reverse order separated by exactly one space. A word is any sequence of non-space characters.
- Input:
" hello world " - Output:
"world hello" - Explanation: Leading and trailing spaces are stripped; the two words swap positions.
Counter-example to show what space handling is required:
- Input:
"a good example" - Output:
"example good a" - Explanation: The three spaces between "good" and "example" collapse to one โ output always has single spaces.
Intuition
The real challenge here is whitespace: leading spaces, trailing spaces, and runs of spaces between words all need to be normalized. Once words are cleanly extracted, reversing their order is trivial. The key insight for the optimal in-place approach is a classic two-reversal trick: reverse the whole string, then reverse each word individually โ the two reversals cancel out within each word but not across them.
Approach 1 โ Split and Reverse
Split the string on whitespace (which automatically handles multiple spaces and trims the ends), reverse the word list, then join with single spaces.
- Call
split()with no arguments โ this tokenizes on any whitespace and discards empty tokens from multiple spaces or leading/trailing spaces - Reverse the resulting word list
- Join the reversed list with a single space
1class Solution:
2 def reverseWords(self, s: str) -> str:
3 words = s.split() # split() handles all whitespace edge cases
4 return ' '.join(reversed(words))Time: O(n) โ each character is visited a constant number of times during splitting, reversing, and joining.
Space: O(n) โ the word array holds all characters.
Approach 2 โ Reverse Twice, In-Place
Avoid the auxiliary word array by working directly on the character buffer. First compact all extra spaces, then reverse the full string, then reverse each word's characters to restore correct orientation.
- Compact the character buffer in-place: skip leading/trailing spaces and reduce runs of spaces to a single separator
- Reverse the entire cleaned string โ words are now in the right order but each word's characters are backwards
- Scan for word boundaries; reverse each word's characters โ this undoes the per-word reversal from step 2 while keeping the word order from step 2
1class Solution:
2 def reverseWords(self, s: str) -> str:
3 chars = list(s)
4 n = len(chars)
5
6 def reverse_range(left: int, right: int) -> None:
7 while left < right:
8 chars[left], chars[right] = chars[right], chars[left]
9 left += 1
10 right -= 1
11
12 # Compact: copy non-space chars, insert exactly one space before each new word
13 write_pos = 0
14 read_pos = 0
15 while read_pos < n:
16 if chars[read_pos] != ' ':
17 if write_pos > 0: # space separates consecutive words
18 chars[write_pos] = ' '
19 write_pos += 1
20 while read_pos < n and chars[read_pos] != ' ':
21 chars[write_pos] = chars[read_pos]
22 write_pos += 1
23 read_pos += 1
24 else:
25 read_pos += 1
26
27 del chars[write_pos:]
28 cleaned_len = write_pos
29
30 reverse_range(0, cleaned_len - 1) # "hello world" -> "dlrow olleh"
31
32 # Reverse each word to restore correct character order
33 word_start = 0
34 for i in range(cleaned_len + 1):
35 if i == cleaned_len or chars[i] == ' ':
36 reverse_range(word_start, i - 1)
37 word_start = i + 1
38
39 return ''.join(chars)Time: O(n) โ the compact pass, the full reversal, and the per-word reversals each touch every character once.
Space: O(1) auxiliary โ the C++ version works in-place on the string. Python and Java require O(n) for the character array since those strings are immutable, but no additional data structures are needed.
Complexity Summary
| Approach | Time | Space | When to use |
|---|---|---|---|
| Split and Reverse | O(n) | O(n) | Default choice โ clear and idiomatic in any language |
| Reverse Twice, In-Place | O(n) | O(1) | When the interviewer asks for O(1) space or hands you a mutable character buffer |
Common Mistakes
- Using
split(' ')in Python instead ofsplit()โ calling split with a single space argument produces empty strings for runs of multiple spaces ("a b".split(' ')โ['a', '', 'b']), while the no-argument form drops them. - Forgetting the
i == lenboundary condition in the reverse-each-word loop โ if you only checks[i] == ' ', the last word never gets reversed because there is no space after it. - Writing two spaces at the join point in the compaction pass โ the
if writePos > 0guard should be checked before inserting the separator space, not inside the inner word-copy loop. - Trimming after calling
split("\\s+")in Java instead of before โ" hello".split("\\s+")produces["", "hello"]because the split happens before leading spaces are consumed;trim()must come first. - Off-by-one when passing
wordStartandi - 1to the reversal helper โ both indices are inclusive, so passingi(the space position) instead ofi - 1includes the space character in the reversal.
Related Problems
Reverse Stringโ the single building block this solution is built from: reverse characters in a rangeRotate Arrayโ uses the exact same three-reversal technique to rotate an integer array in placeValid Palindromeโ two-pointer traversal with non-trivial character filtering, same category of string scan problemsLongest Common Prefixโ column-by-column string comparison; good follow-up for thinking about string scanning patternsIs Subsequenceโ two-pointer technique on strings, useful contrast for understanding when pointers move independently vs together