Understand
30-second explanation
Build the interview-ready mental model before comparing implementations.
Reverse the ORDER of words, not the characters. The clean answer is: trim, split on runs of whitespace, reverse the list, and join with single spaces — O(n) time, O(n) space. The follow-up they often ask is the O(1) extra-space in-place version on a char array: reverse the whole string, then reverse each word, then squeeze the spaces.
Interview contextWhat is testedWhere candidates slipHow to stand outExplore interview contextHide interview context
What's being tested
Whether you handle messy whitespace correctly (leading, trailing, multiple inner spaces) and whether you know the in-place double-reverse technique when asked to avoid extra space.
Where candidates slip
Reversing the characters instead of the word order, or producing extra/leading/trailing spaces from naive splitting on a single ' '.
How to stand out
Give the clean split/reverse/join first, call out the whitespace normalization explicitly, then volunteer the O(1)-extra char-array approach (reverse all, reverse each word, clean spaces) before being asked.
Choose
Compare the available approaches
Use constraints and trade-offs to select the route you can defend in an interview.
Interactive decision treeInteractiveChoose the right approachFirst decision previewReverse word ORDER, normalize spacesO(1) extra space required?NoYes (mutable buffer)Explore the full treeCollapse the tree
Learn & trace
Build each solution step by step
Move from the core idea to a visual trace, implementation, proof, and edge cases.
Approach 1 of 2 · Optimal
Split, Reverse, Join (Optimal & Idiomatic)
1Hint 1Explore hintHide hint
If you had the words as a clean list with no empty entries, the answer would just be that list, reversed and rejoined. How do you get such a list from a string with arbitrary spaces?
2Hint 2Explore hintHide hint
Splitting on a run of whitespace (not a single space) and dropping empties gives you exactly the words. Python's s.split() does this by default; Java needs s.trim().split("\\s+").
3Hint 3Explore hintHide hint
Reverse the list of words and join with a single space. Don't append a trailing space — join handles the separators.
A · Core idea
The cleanest mental model: the sentence is a list of words glued together by arbitrary whitespace. If we can extract that list cleanly, the rest is trivial — reverse it and glue it back with single spaces.
Why splitting on whitespace *runs* is the whole trick. The hard part of this problem is not reversing — it's the spaces. Splitting on a single literal ' ' is a classic bug: "a b" would produce ["a", "", "b"] with an empty token for the doubled space, and leading/trailing spaces produce empty tokens at the ends. Splitting on a run of whitespace and discarding empties (s.split() in Python, s.trim().split("\\s+") in Java) collapses all of that automatically. After this single step the words list is already clean — no empties, no padding.
Why join beats manual concatenation. Once you reverse the words, the temptation is to loop and append word + " ", then strip the trailing space. That works but invites the off-by-one trailing-space bug. " ".join(words) (or building with a separator-aware loop) places a space between words only, so the result is automatically free of leading and trailing spaces. Let the join own the separators.
Why this is genuinely O(n). Each character is read once during the split and written once during the join; reversing a list of w words is O(w) ≤ O(n). The space is O(n) because we materialize the words list and a fresh output string — unavoidable when the input is an immutable String. That O(n) space is exactly what the follow-up question targets, which is the cue to mention the in-place approach.
Why it's the right *first* answer. It's short, obviously correct, and makes the whitespace handling explicit and auditable. In an interview, ship this, state its O(n) space, and then say 'if you want O(1) extra space on a mutable buffer, here's the double-reverse trick' — showing you know both the pragmatic and the constrained solution.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
s = " the sky is blue "Interactive diagram
Two routes to the answer
splitPick based on the space constraint. Split/reverse/join is the default; the double-reverse is the O(1)-extra follow-up.
"blue is sky the"C · Code with teaching comments
D · Why it works and complexityO(n) timeO(n) spaceOpen the invariant and proofExplore the proofHide the proof
The entire difficulty is whitespace, not reversal. Splitting on a whitespace run (rather than a single space) and joining with a single space makes leading/trailing/duplicate spaces vanish without any special-case code. Recognizing that the right tokenizer eliminates edge cases is the lesson.
ComplexityO(n) time, O(n) space — Splitting scans the string once (O(n)), reversing is O(w) over w words, joining writes O(n) characters. The words list and output are O(n) space.
E · Edge cases and pitfalls6s = " " (spaces only) — Constraints guarantee ≥1 word, but defensively split() → [] and join → "" (no crash).Explore edge casesHide edge cases
Edge cases handled
s = " " (spaces only)Constraints guarantee ≥1 word, but defensively split() → [] and join → "" (no crash).s = "word"Single word → list of one → join returns it unchanged: "word".s = "a b"Double space collapses; words = ['a','b'] → "b a".
Pitfalls
- Splitting on a single ' ' instead of a whitespace run — yields empty tokens for duplicate/edge spaces.
- Manually appending word + ' ' and forgetting to strip the trailing space.
- Reversing the characters of the string instead of the order of words.
Approach 2 of 2
In-Place Double Reverse (O(1) Extra Space)
1Hint 1Explore hintHide hint
Reverse the ENTIRE string. Now the words appear in the right ORDER but each word is spelled backwards. What second operation fixes the spelling without disturbing the order?
2Hint 2Explore hintHide hint
Reverse each individual word in place. Two reverses cancel out within a word (restoring its letters) but the global reverse already moved the words into reversed order.
3Hint 3Explore hintHide hint
Finally, walk the buffer with two pointers to remove leading/trailing spaces and collapse inner runs to a single space — all done in the same array.
A · Core idea
This is the technique interviewers are fishing for with the follow-up. It rests on a small, beautiful identity: reversing twice returns you to the original. We exploit that asymmetrically — reverse globally once, reverse locally (per word) once — so words end up reordered while their internal letters are restored.
Step 1 — reverse the whole buffer. Take "the sky" → "yks eht". Now the words are in the final order we want (sky then the), but each word's characters are backwards. The global reverse did the reordering; it just damaged the spelling as a side effect.
Step 2 — reverse each word in place. Walk the buffer, find each maximal non-space run, and reverse just that segment: "yks" → "sky", "eht" → "the". Because reversing a word twice (once by the global flip, once here) is the identity, every word's letters snap back to correct order — but their positions in the sentence stay where the global reverse put them. That's the crux: the two reverses operate at different granularities, so they don't fully cancel.
Step 3 — clean the spaces. The reversing steps preserve whatever messy spacing the input had. A final two-pointer compaction pass squeezes it: a write pointer i lags a read pointer j; we skip leading/duplicate spaces, copy each word, and emit exactly one space between words. Since i never overtakes j, the rewrite is safe in the same array. We return the buffer truncated to length i.
Why we still allocate an output string. True O(1) total space is impossible when the signature returns a String (immutable), so 'O(1) extra space' means O(1) auxiliary space beyond the mutable buffer we're handed/created. On a language with mutable strings (or when the input genuinely is a char[]), this is a real in-place algorithm. Stating that distinction explicitly is exactly the nuance interviewers reward.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
a = ['t','h','e',' ','s','k','y'] ("the sky")Interactive diagram
Why two reverses work
reverse allGlobal reverse fixes word order; per-word reverse fixes spelling. Different granularities, so they don't fully cancel.
"sky the"C · Code with teaching comments
Reference implementation previewpublic String reverseWords(String s) { char[] a = s.toCharArray(); int n = a.length; reverse(a, 0, n - 1); // 1. reverse the whole string reverseEachWord(a, n); // 2. reverse each word backExplore the full codeHide the full code
D · Why it works and complexityO(n) timeO(1) spaceOpen the invariant and proofExplore the proofHide the proof
Reverse-the-whole-then-reverse-each-part is a reusable template: it reorders groups while preserving order within groups, in O(1) extra space. The same trick rotates arrays (Rotate Array, LeetCode 189) — reverse all, reverse the two halves. Spot it whenever you need 'flip the big structure but keep the small structures intact.'
ComplexityO(n) time, O(1) space — Three linear passes (reverse all, reverse each word, clean spaces) = O(n) time. Everything happens inside the existing char array, so extra space is O(1) (ignoring the output the language forces us to allocate).
E · Edge cases and pitfalls6a = " hello " (padded) — Reverses keep the padding; cleanSpaces strips leading/trailing and collapses → "hello".Explore edge casesHide edge cases
Edge cases handled
a = " hello " (padded)Reverses keep the padding; cleanSpaces strips leading/trailing and collapses → "hello".a = "a b"Reverse all → "b a"; reverse each → "b a"; clean → "b a".single word "abc"Reverse all → "cba"; reverse the word → "abc"; clean → "abc".
Pitfalls
- Reversing the whole string but forgetting to reverse each word back — leaves words spelled backwards.
- Letting the write pointer overtake the read pointer during compaction — corrupts data.
- Claiming O(1) total space — the returned String is a fresh allocation; it's O(1) AUXILIARY space.
Practice
Try the solution yourself
Edit the optimal implementation, test another input, and observe the result.
Editable code previewpublic String reverseWords(String s) { String[] words = s.trim().split("\\s+"); StringBuilder sb = new StringBuilder(); for (int i = words.length - 1; i >= 0; i--) { sb.append(words[i]);Explore the playgroundClose the playground
Avoid mistakes
Recognize the interview traps
Understand why common attempts fail before reviewing the corrected implementation.
1Splitting on a single space
split(' ') (Java) or split(' ') (Python) on ' a b ' yields empty strings for every extra space, which then become stray spaces in the output.
Explore the code comparisonHide the code comparison
Splitting on a single space
split(' ') (Java) or split(' ') (Python) on ' a b ' yields empty strings for every extra space, which then become stray spaces in the output.
Don't write this
words = s.split(' ') # ['', '', 'a', '', 'b', ''] for ' a b '
return ' '.join(reversed(words))Write this instead
words = s.split() # ['a', 'b'] — runs collapsed, edges trimmed
return ' '.join(reversed(words))2Trailing space from manual concatenation
Appending word + ' ' in a loop leaves a dangling space after the last word, violating the 'no trailing space' rule.
Explore the code comparisonHide the code comparison
Trailing space from manual concatenation
Appending word + ' ' in a loop leaves a dangling space after the last word, violating the 'no trailing space' rule.
Don't write this
for (int i = words.length - 1; i >= 0; i--) {
sb.append(words[i]).append(' '); // trailing space after last word
}
return sb.toString();Write this instead
for (int i = words.length - 1; i >= 0; i--) {
sb.append(words[i]);
if (i > 0) sb.append(' ');
}
return sb.toString();3Reversing characters, not words
Doing a single full-string reverse and stopping there gives 'eulb yks eht' — the words are backwards AND in the wrong internal order.
Explore the code comparisonHide the code comparison
Reversing characters, not words
Doing a single full-string reverse and stopping there gives 'eulb yks eht' — the words are backwards AND in the wrong internal order.
Don't write this
return s[::-1] # reverses characters, not word orderWrite this instead
return ' '.join(reversed(s.split()))Revise
Carry the pattern into the interview
Pattern to remember
Tokenize + reverse order (or reverse-whole-then-reverse-each-word)
Code pattern to memorize
# Pragmatic:
words = s.split() # drops leading/trailing + collapses runs
return " ".join(reversed(words))
# In-place O(1) extra (char array):
reverse(a, 0, n-1) # whole string
reverse each word in place
clean spaces (trim + single)Rules to remember
- 1Reverse the order of words, not the letters in them.
"the sky"→"sky the", never"yks eht". - 2Collapse whitespace. Leading, trailing, and multiple inner spaces must become single separators —
" a b "→"b a". - 3`split()` with no argument already trims and collapses runs in Python; in Java use
trim()thensplit("\\s+"). - 4The O(1)-extra trick is reverse-whole-then-reverse-each-word — reversing twice (globally, then per word) restores letter order while flipping word order.
- 5Strings are immutable in Java/Python, so 'in place' means operating on a
char[]/ list, not the String itself.
Use this pattern when
- Re-ordering tokens (words, segments) while preserving each token internally
- Whitespace normalization is part of the spec
- Interviewer adds 'can you do it with O(1) extra space?' → the double-reverse trick
- Any 'reverse the groups but not within groups' framing
Choose another pattern when
- Reverse the characters of the whole string → a single reverse, far simpler
- Reverse letters within each word but keep word order (LeetCode 557) → reverse each token in place
- Words are fixed-width / no whitespace cleanup needed → simpler split
- Need to preserve original spacing → don't collapse runs
Interview takeaway
Reverse Words tests two things: careful whitespace handling (the part that actually trips people), and whether you know the reverse-whole-then-reverse-each-word trick for O(1) extra space. The split/reverse/join version is the right first answer; the in-place version is the medium-level follow-up.
Continue
Transfer the pattern to another problem
Use a direct variation or pattern sibling to prove the idea is reusable.
Transferable patternTwo-pointer reversal + tokenization. The headline technique is reverse-whole-then-reverse-each-part, which reorders groups while preserving within-group order in O(1) extra space — reused directly in Rotate Array and Reverse Words II. The split/reverse/join version teaches that the right tokenizer dissolves whitespace edge cases.
Practice queueDirect variations and pattern siblings
Direct follow-ups
- Reverse Words in a String IIIComing soonReverse the letters WITHIN each word but keep word order — just the per-word reverse step.
- Reverse Words in a String IIComing soonInput is a char[] with single spaces — the pure in-place double-reverse, no space cleanup needed.
- Rotate ArrayComing soonSame reverse-the-whole-then-reverse-the-parts trick rotates an array in O(1) extra space.
- Reverse StringComing soonThe primitive this problem is built on: two-pointer in-place character reversal.