Skip to content
← All posts

Reverse Words in a String III: Per-Word Reversal in One Line

4 min read
leetcodeproblemeasystrings

LeetCode #557 Reverse Words in a String III asks you to reverse the characters within each word of a sentence, while keeping the words themselves in their original order. This is different from Reverse Words in a String (LeetCode 151), which reverses the order of the words. Here, the words stay put. Only the letters inside each word get flipped.

The problem

Given a string s, reverse the order of characters in each word within the sentence while preserving whitespace and initial word order.

Input:  "Let's take LeetCode contest"
Output: "s'teL ekat edoCteeL tsetnoc"

Each word is reversed individually. The spaces between words remain exactly where they were.

inputLet'stakeLeetCodecontestreversereversereversereverseoutputs'teLekatedoCteeLtsetnoc
Each word is reversed individually while staying in its original position. Spaces between words are preserved.

The approach

The cleanest way to solve this is the split-reverse-join pattern:

  1. Split the string on spaces to get a list of words.
  2. Reverse each word individually.
  3. Join the reversed words back together with spaces.

Python makes this a one-liner thanks to list comprehensions and string slicing. You split with split(), reverse each word with [::-1], and glue everything back with " ".join(...).

There is also an in-place two-pointer approach. You walk through the string character by character, find the start and end of each word, then use two pointers to swap characters from the outside in. This avoids creating extra strings, which matters in languages like C++ where you can modify the string directly. In Python, strings are immutable, so the split-reverse-join approach is both idiomatic and efficient.

LeetCode 151 (Reverse Words in a String) reverses the order of the words themselves, turning "the sky is blue" into "blue is sky the". LeetCode 557 reverses the characters within each word, keeping words in place. The two problems look similar but require different operations.

The solution

def reverseWords(s: str) -> str:
    return ' '.join(word[::-1] for word in s.split(' '))

Here is what each piece does:

  1. s.split(' ') splits on space characters, producing a list like ["Let's", "take", "LeetCode", "contest"].
  2. word[::-1] reverses each word. "Let's" becomes "s'teL", "take" becomes "ekat", and so on.
  3. ' '.join(...) concatenates all the reversed words with a single space between each one.

The entire solution fits in one line. There are no edge-case branches because split and join handle the boundaries naturally.

Step-by-step walkthrough

Step 1: Split the string by spaces

Let'stakeLeetCodecontest

s.split(" ") produces four separate words: ["Let's", "take", "LeetCode", "contest"].

Step 2: Reverse each word individually

s'teLekatedoCteeLtsetnoc

Each word is reversed on its own. "Let's" becomes "s'teL", "take" becomes "ekat", and so on.

Step 3: Join with spaces

s'teLekatedoCteeLtsetnoc

" ".join(...) puts the reversed words back together with spaces. Final result: "s'teL ekat edoCteeL tsetnoc".

The process is clean and mechanical. Split, reverse each piece, join. No index arithmetic, no pointer management.

Complexity analysis

ApproachTimeSpace
Split + reverse + joinO(n)O(n)

Time: O(n). Splitting the string visits every character once. Reversing all words visits every character once more. Joining visits every character a third time. That is three passes through n characters, giving O(3n) which simplifies to O(n).

Space: O(n). The split produces a list of words, and the join creates a new string. Both require space proportional to the length of the input.

The building blocks

Split-transform-join pattern

The split-transform-join pattern appears in many string problems. The template looks like this:

result = delimiter.join(transform(part) for part in s.split(delimiter))

You break the string into pieces at a known delimiter, apply some transformation to each piece, then reassemble. For this problem the delimiter is a space and the transformation is reversal. But the same pattern works for problems like changing the case of each word, trimming whitespace from each segment, or encoding each token.

When a problem says "do X to each word" or "do X to each segment," think split-transform-join first. It is almost always the simplest approach, and the code reads like a description of the algorithm itself.

Edge cases

Before submitting, make sure your solution handles these scenarios:

  • Single word like s = "hello": there is nothing to split, so you just reverse the one word. Result: "olleh".
  • Single character like s = "a": reversing a single character gives you back the same character. Result: "a".
  • Words of length 1 like s = "I am a": each single-letter word reverses to itself. Result: "I ma a". Only multi-character words visibly change.
  • Palindrome words like s = "madam racecar": reversing a palindrome produces the same word. Result: "madam racecar". The output matches the input.
  • All same characters like s = "aaa bbb": reversing uniform words has no visible effect. Result: "aaa bbb".

The one-liner handles all of these naturally. split(' ') always produces at least one element, and reversing an empty or single-character string is a no-op.

From understanding to recall

This problem is easy to understand. Split on spaces, reverse each word, join back. Most people can explain the approach in seconds. But under interview pressure, you might hesitate on the details. Do you use split(' ') or split()? Does [::-1] work on strings or only on lists? Is it ' '.join(...) or " ".join(...)?

These are recall problems, not understanding problems. Spaced repetition closes this gap. You write the solution from memory at increasing intervals. After a few reps, the one-liner flows out automatically. You stop double-checking whether split or join comes first because your hands already know the pattern.

Related posts

CodeBricks breaks string problems into their core patterns and drills each one until it sticks. The split-transform-join pattern you used here shows up across dozens of problems. Once you can write it from memory, you will recognize and solve new variations without hesitation.