Length of Last Word
The final character may be a space, so the right edge of the string is not necessarily part of the answer. The clean Length of Last Word solution is a…

Length of Last Word
Given a string containing words and spaces, return the length of its last word, where a word is a maximal substring containing only non-space characters.
Constraints
- 1 <= s.length <= 10^4
- s consists only of English letters and spaces ' '
- s contains at least one word
Important details
- Spaces may occur around or between words.
- The last word is determined by non-space characters at the end of the string, ignoring trailing spaces.
Key topics
The final character may be a space, so the right edge of the string is not necessarily part of the answer. The clean Length of Last Word solution is a two-phase reverse scan: skip trailing spaces, then count the final run of non-space characters.
Read the Contract at the Boundary
A word is a contiguous run of non-space characters. The answer is the length of the rightmost such run.
For example:
"Hello World" -> 5
"Hello World " -> 5
" fly me to moon" -> 4
The input contains English letters and the literal space character ' '. Spaces can appear at the beginning, between words, or at the end. At least one word exists.
That contract gives us the recognition cue:
The answer is attached to the right boundary, but the right boundary may contain irrelevant padding.
So start at the right. We need only two pieces of state:
i: the current position in the stringcount: the number of characters in the final word found so far
This is the State Tracking & Invariants lens in miniature. The index tracks where the scan is. The counter stores the only summary that survives the scan.
Start With the Natural Split
The obvious Python approach is to split the string into pieces and inspect the final word:
def length_of_last_word(s: str) -> int:
words = s.split()
return len(words[-1])
This is readable, and under the stated contract it works. Python's whitespace-aware split() removes empty pieces caused by repeated or surrounding spaces.
A manual split using the literal delimiter is more fragile:
parts = s.split(" ")
For this input:
"Hello World "
the result contains empty strings after "World". Selecting parts[-1] would return an empty string unless you filter those pieces or remove trailing spaces first.
Splitting is a valid choice when extra storage is acceptable. But it materializes every piece even though the problem asks for one integer. The earlier words cannot affect the answer once we have crossed the separator before the final word.
That gives us a useful decision rule:
When the answer is one boundary-defined run, ask whether a scan can find that run without storing everything before it.
Here, it can.
Derive the Two-Phase Reverse Scan
The reverse scan has two separate obligations. Keeping them separate prevents the common mistake of counting padding as part of the word.
Phase 1: Skip trailing spaces
Set i to the final index:
i = len(s) - 1
While i points to a space, move left:
while i >= 0 and s[i] == " ":
i -= 1
When this loop stops, i is either:
- on the final character of the last word, or
- outside the string on the left
The problem guarantees at least one word, so the first case will occur for valid input. The bounds check still matters because it keeps indexing safe while the pointer moves.
Phase 2: Count the final word
Now move left while the current character is not a space:
count = 0
while i >= 0 and s[i] != " ":
count += 1
i -= 1
The loop stops at the first space before the word or after moving past the beginning of the string. Either way, count is the length of the final word.
The complete derivation is:
- Start at the last character.
- Ignore every trailing space.
- Count non-space characters while moving left.
- Stop at a space or the left boundary.
- Return the count.
A forward scan with a resettable counter also works: count the current word, reset after spaces, and return the final count. The reverse scan mirrors the question more directly. Once it finishes the last word, it stops; it does not need to process earlier words.
Name the Invariant
An invariant is a statement that remains true as a loop runs. It turns “this code seems to work” into a checkable correctness argument.
After the first loop:
If
iis in bounds,s[i]is the last character of the last word, and every character to its right is a trailing space.
The first phase has therefore established the right edge of the answer.
During the second loop:
countequals the number of non-space characters already consumed from the end of the last word.
At every step:
imarks the next character to inspect.countrecords how many characters from the final word have already been counted.- No character to the right of
ineeds to be examined again.
The second loop terminates when it reaches a space or the left boundary. Because the first phase started at the final word's right edge, and the second phase stops at its left boundary, every character in the final word is counted exactly once. The preceding word cannot be included because the separator stops the loop.
Each variable has a single job:
itracks the scan frontier.countstores the answer summary.
That is enough state. We do not need the word itself, a list of tokens, or a second string.
Implement the Python Scan
def length_of_last_word(s: str) -> int:
i = len(s) - 1
# Skip trailing spaces.
while i >= 0 and s[i] == " ":
i -= 1
count = 0
# Count the final run of non-space characters.
while i >= 0 and s[i] != " ":
count += 1
i -= 1
return count
The order of each loop condition is deliberate:
i >= 0 and s[i] == " "
Python evaluates the left side first. If i is already -1, it does not attempt to access s[-1] in this condition. The bounds check must come before the indexing operation.
The two loops also establish a clean handoff:
- The first loop finds the word's right edge.
- The second loop measures the word while crossing it from right to left.
Keeping those responsibilities visible is better interview code than hiding the behavior behind several string helpers when the point is to demonstrate boundary-safe state tracking.
Dry-Run the Spacing Traps
Consider:
s = " fly me to the moon "
The scan begins at the final space.
Skip the trailing padding
The pointer moves left across both final spaces:
" fly me to the moon "
^ i
After two moves, i points to the final character of "moon":
" fly me to the moon "
^ i
Count the final word
Now the second loop consumes:
| Character | count after reading it |
|---|---|
n | 1 |
o | 2 |
o | 3 |
m | 4 |
The next character to the left is a space, so the loop stops and returns 4.
The earlier spaces do not matter. Neither do the words "fly", "me", or "to". The reverse scan discards everything outside the final non-space run.
Other boundary cases follow the same state transitions:
"word": there are no trailing spaces; count all four characters, then stop at the left boundary." word": skip nothing at the end, count"word", and stop after reaching index0."one two": count"two"and stop at the nearest space; repeated internal spaces cause no problem."hello ": skip all trailing spaces before counting"hello"."a": count one character and finish safely.
Weak implementations usually fail in one of four ways:
- They count trailing spaces as if they were part of the word.
- They skip only one trailing space instead of all of them.
- They index
s[i]before checking thati >= 0. - They trim the string and return its total length, which counts every word rather than only the last one.
When debugging, inspect the pointer before inspecting the answer. If i has not reached the final word's right edge, the counter is being asked to solve the wrong problem.
Complexity: Scan Versus Split
Let n be the length of the string.
The reverse scan runs in O(n) time in the worst case. If the final word is near the right edge, it may inspect only the trailing spaces and the final word. If the final word reaches the beginning, it inspects the entire string. Either way, the work is bounded by n.
The scan uses O(1) auxiliary space:
- one index
- one counter
A split-based solution is also linear in ordinary string-processing terms, but it creates additional pieces or token storage. Its extra space grows with the input and the number of pieces. The exact allocation details depend on the language and implementation, but it does not have the same constant-space behavior as the direct scan.
My interview rule is conditional rather than ideological:
- Choose splitting when its clarity is valuable and its empty-token behavior is handled.
- Choose the reverse scan when constant auxiliary space matters or when you want the state transitions to be explicit.
The reverse scan is not automatically faster in every runtime. Its strongest advantage is that it stores only the scalar result the problem asks for.
Edge Cases and the Transfer Rule
Before submitting, check the contract against these cases:
- trailing spaces:
"word " - leading spaces:
" word" - repeated internal spaces:
"one two" - one word:
"word" - a final word beginning at index
0:"word" - the literal separator:
' ', not an arbitrary category of whitespace
That last point is easy to blur. This problem defines separators as literal spaces. Do not silently replace the condition with a broader whitespace test unless the problem contract allows tabs, newlines, or other characters.
The at-least-one-word guarantee also matters. Under this contract, an all-space string will not appear. If a different version allowed it, you would need an explicit policy for returning 0 or reporting that no word exists. Do not let an unstated input condition decide your algorithm accidentally.
The reusable pattern is narrow but valuable:
When the answer is the final contiguous run satisfying a condition, locate the right boundary first, discard irrelevant padding, then maintain the smallest summary while crossing the run.
For this problem, the condition is “is not a literal space,” and the summary is a count. Clear the padding. Find the signal. Count only what survives the boundary.
References
Research updated Sep 7, 2026


