Skip to main content

Reverse Words in a String

MEDIUMProblemSolveExternal Links

Description

Given an input string s, reverse the order of the words.

A word is defined as a sequence of non-space characters. The words in s will be separated by at least one space.

Return a string of the words in reverse order, concatenated by a single space.

Note that s may contain leading or trailing spaces, or multiple spaces between two words. The returned string should only have a single space separating the words. Do not include any extra spaces.

Examples

Example 1

Input: s = "the sky is blue"

Output: "blue is sky the"

Explanation: The string has four words: "the", "sky", "is", "blue". Reversing their order gives "blue is sky the". There are no extra spaces to worry about in this case.

Example 2

Input: s = " hello world "

Output: "world hello"

Explanation: The input has leading and trailing spaces, but the output must not. The two words are extracted as "hello" and "world", then reversed to "world hello" with a single space between them.

Example 3

Input: s = "a good example"

Output: "example good a"

Explanation: Multiple spaces between "good" and "example" are reduced to a single space in the output. The three words are reversed to "example good a".

Constraints

  • 1 ≤ s.length ≤ 10^4
  • s contains English letters (upper-case and lower-case), digits, and spaces ' '
  • There is at least one word in s

Editorial

Brute Force - Split and Reverse

Intuition

The most direct approach is to break the problem into three simple steps: split the string into words, reverse the list of words, and join them back together.

Most languages provide a built-in split function that can handle multiple spaces automatically. For instance, Python's split() (without arguments) splits on any whitespace and discards empty strings. After splitting, we get a clean list of words. Reversing that list and joining with a single space produces the desired output.

Think of it like reading words off a page, writing them on sticky notes (one word per note), flipping the stack of notes upside down, and then reading them back.

Step-by-Step Explanation

Let's trace through with s = "a good example":

Step 1: Split the string into words. The split operation handles the multiple spaces between "good" and "example" automatically.

  • words = ["a", "good", "example"]

Step 2: Reverse the list of words.

  • reversed = ["example", "good", "a"]

Step 3: Join the reversed words with a single space.

  • result = "example good a"

Step 4: Return "example good a".

Split, Reverse, Join — Watch the three phases: splitting the string into a word array, reversing that array in place, and joining the reversed words into the final result.

Algorithm

  1. Split the string s into a list of words (handling multiple spaces automatically)
  2. Reverse the list of words
  3. Join the reversed list with a single space between each word
  4. Return the result

Code

class Solution {
public:
    string reverseWords(string s) {
        // Split into words
        vector<string> words;
        istringstream iss(s);
        string word;
        while (iss >> word) {
            words.push_back(word);
        }
        
        // Reverse the word list
        reverse(words.begin(), words.end());
        
        // Join with single space
        string result;
        for (int i = 0; i < words.size(); i++) {
            if (i > 0) result += " ";
            result += words[i];
        }
        return result;
    }
};
class Solution:
    def reverseWords(self, s: str) -> str:
        # split() handles multiple spaces, leading/trailing spaces
        words = s.split()
        # Reverse and join with single space
        return " ".join(words[::-1])
class Solution {
    public String reverseWords(String s) {
        // Trim and split on one or more spaces
        String[] words = s.trim().split("\\s+");
        
        // Reverse the array
        int left = 0, right = words.length - 1;
        while (left < right) {
            String temp = words[left];
            words[left] = words[right];
            words[right] = temp;
            left++;
            right--;
        }
        
        // Join with single space
        return String.join(" ", words);
    }
}

Complexity Analysis

Time Complexity: O(n)

Splitting the string traverses all n characters once. Reversing the word list takes O(k) where k is the number of words (at most n/2). Joining the words back scans all characters again. Total: O(n).

Space Complexity: O(n)

We store all words in a list, which collectively holds up to n characters. The joined output string also takes O(n) space. Total extra space: O(n).

Why This Approach Is Not Efficient

The split-reverse-join approach works correctly and runs in O(n) time, but it uses O(n) extra space for storing the word list. In an interview setting, the follow-up question often asks: "Can you do this with O(1) extra space?"

In languages where strings are mutable (like C/C++ with character arrays), there is an elegant in-place technique. The insight: if we reverse the entire string first, the words end up in the correct order but each word itself is backwards. Then we reverse each individual word to fix it. Finally, we clean up any extra spaces.

For example:

  • Original: "the sky is blue"
  • Reverse entire string: "eulb si yks eht"
  • Reverse each word: "blue is sky the"

This approach modifies the string in place, avoiding the extra word list entirely.

Optimal Approach - Reverse Entire String Then Reverse Each Word

Intuition

The core idea is a beautiful trick: two reverses make a right.

Imagine you have a sentence written on a strip of paper: "the sky is blue". If you hold the strip up to a mirror (reverse the whole thing), you get "eulb si yks eht". The words are now in the correct order ("blue" comes first, "the" comes last), but each individual word is spelled backwards.

Now, if you reverse each word individually, you fix the spelling: "blue is sky the". That is exactly the answer!

The algorithm works in three phases:

  1. Reverse the entire character array — this puts the words in the right order but backwards
  2. Reverse each individual word — this fixes the letter order within each word
  3. Clean up spaces — compact multiple spaces and remove leading/trailing spaces

This approach is particularly valuable because it can be done in-place with O(1) extra space in languages with mutable strings.

Step-by-Step Explanation

Let us trace through with s = "the sky is blue":

Step 1: Convert string to a character array: ['t','h','e',' ','s','k','y',' ','i','s',' ','b','l','u','e'].

Step 2: Reverse the entire array.

  • Before: ['t','h','e',' ','s','k','y',' ','i','s',' ','b','l','u','e']
  • After: ['e','u','l','b',' ','s','i',' ','y','k','s',' ','e','h','t']
  • The string reads "eulb si yks eht" — words are in reverse order but each word is backwards.

Step 3: Reverse the first word "eulb" (indices 0-3).

  • ['b','l','u','e',' ','s','i',' ','y','k','s',' ','e','h','t']
  • First word fixed: "blue".

Step 4: Reverse the second word "si" (indices 5-6).

  • ['b','l','u','e',' ','i','s',' ','y','k','s',' ','e','h','t']
  • Second word fixed: "is".

Step 5: Reverse the third word "yks" (indices 8-10).

  • ['b','l','u','e',' ','i','s',' ','s','k','y',' ','e','h','t']
  • Third word fixed: "sky".

Step 6: Reverse the fourth word "eht" (indices 12-14).

  • ['b','l','u','e',' ','i','s',' ','s','k','y',' ','t','h','e']
  • Fourth word fixed: "the".

Step 7: Join and return: "blue is sky the".

Two-Phase Reversal: Entire String, Then Each Word — Watch the elegant two-phase trick: first reverse the whole string (putting words in the right order but backwards), then reverse each individual word to fix the spelling.

Algorithm

  1. Convert the string to a mutable character array
  2. Trim and compact spaces: Remove leading/trailing spaces and reduce multiple spaces to single spaces (write pointer technique)
  3. Reverse the entire character array using two pointers swapping from both ends
  4. Reverse each individual word: scan for word boundaries (start/end of non-space sequences) and reverse each word in place
  5. Convert the character array back to a string and return

Code

class Solution {
public:
    string reverseWords(string s) {
        // Step 1: Clean up spaces and compact
        int n = s.size();
        int write = 0;
        for (int read = 0; read < n; read++) {
            if (s[read] != ' ') {
                if (write > 0) s[write++] = ' ';
                while (read < n && s[read] != ' ') {
                    s[write++] = s[read++];
                }
            }
        }
        s.resize(write);
        n = write;
        
        // Step 2: Reverse entire string
        reverse(s.begin(), s.end());
        
        // Step 3: Reverse each word
        int start = 0;
        for (int i = 0; i <= n; i++) {
            if (i == n || s[i] == ' ') {
                reverse(s.begin() + start, s.begin() + i);
                start = i + 1;
            }
        }
        
        return s;
    }
};
class Solution:
    def reverseWords(self, s: str) -> str:
        # Convert to list for mutability
        chars = list(s)
        
        # Step 1: Clean up spaces - compact to single spaces, no leading/trailing
        write = 0
        n = len(chars)
        read = 0
        while read < n:
            if chars[read] != ' ':
                if write > 0:
                    chars[write] = ' '
                    write += 1
                while read < n and chars[read] != ' ':
                    chars[write] = chars[read]
                    write += 1
                    read += 1
            else:
                read += 1
        chars = chars[:write]
        
        # Step 2: Reverse entire array
        chars.reverse()
        
        # Step 3: Reverse each word
        start = 0
        for i in range(len(chars) + 1):
            if i == len(chars) or chars[i] == ' ':
                # Reverse chars[start:i]
                left, right = start, i - 1
                while left < right:
                    chars[left], chars[right] = chars[right], chars[left]
                    left += 1
                    right -= 1
                start = i + 1
        
        return ''.join(chars)
class Solution {
    public String reverseWords(String s) {
        char[] chars = s.toCharArray();
        int n = chars.length;
        
        // Step 1: Clean up spaces
        int write = 0;
        for (int read = 0; read < n; read++) {
            if (chars[read] != ' ') {
                if (write > 0) chars[write++] = ' ';
                while (read < n && chars[read] != ' ') {
                    chars[write++] = chars[read++];
                }
            }
        }
        
        // Step 2: Reverse entire cleaned portion
        reverse(chars, 0, write - 1);
        
        // Step 3: Reverse each word
        int start = 0;
        for (int i = 0; i <= write; i++) {
            if (i == write || chars[i] == ' ') {
                reverse(chars, start, i - 1);
                start = i + 1;
            }
        }
        
        return new String(chars, 0, write);
    }
    
    private void reverse(char[] chars, int left, int right) {
        while (left < right) {
            char temp = chars[left];
            chars[left] = chars[right];
            chars[right] = temp;
            left++;
            right--;
        }
    }
}

Complexity Analysis

Time Complexity: O(n)

Each phase traverses the string once: space cleanup is O(n), full string reversal is O(n), and reversing each word is O(n) total (since word lengths sum to at most n). Overall: O(n).

Space Complexity: O(1) extra space (in C++ with mutable strings)

The reversal is done in-place on the character array. No word list, no extra string copies. Only a few pointer variables are used.

Note: In Python and Java, strings are immutable, so we must convert to a character array first which takes O(n) space for the array. However, the algorithm itself uses O(1) extra space beyond the character array, which is an improvement over the brute force approach that builds a separate word list.