Problem statement
Given a string s, return the length of the longest substring — a contiguous run of characters — in which no character appears twice.
Examples
- Input
s = "abcabcbb"
- Output
3
Why: "abc" is the longest run without a repeat.
- Input
s = "bbbbb"
- Output
1
Why: Every longer run repeats "b".
- Input
s = "pwwkew"
- Output
3
Why: "wke". Note "pwke" is not contiguous, so it does not count.
Constraints
- 0 ≤ s.length ≤ 5 × 10⁴
- s may contain letters, digits, symbols and spaces.
How to answer it out loud
What it tests: Sliding-window reasoning, choosing what state to keep, and avoiding the off-by-one when the left edge moves.
- 1Clarify
Clarify the character set, whether case matters, and what an empty string returns.
- 2Implement
Grow a window to the right and store each character’s last index; when a repeat falls inside the window, jump the left edge past it.
- 3Verify
Trace "abba", "", and "pwwkew"; explain O(n) time and why the left edge never moves backwards.
From brute force to the best solution
| Approach | Idea | Time | Space |
|---|---|---|---|
| Check every substring | For each start, extend until a repeat appears. | O(n²) | O(min(n, alphabet)) |
| Sliding window + last-seen indexBest | When a character repeats inside the window, jump the left edge past its previous position. | O(n) | O(min(n, alphabet)) |
The left edge only ever moves forward. Only jump it when the previous copy is inside the current window — otherwise "abba" returns 3 instead of 2.
Reference solution
Each version is self-contained and has been run against the examples and test cases on this page.
def length_of_longest_substring(s: str) -> int: last_seen = {} # char -> most recent index best = left = 0 for right, ch in enumerate(s): if last_seen.get(ch, -1) >= left: # repeat inside the current window left = last_seen[ch] + 1 # jump past the earlier copy last_seen[ch] = right best = max(best, right - left + 1) return best- Time
- O(n)
- Space
- O(min(n, alphabet))
- Approach
- Sliding window + last-seen index
Edge cases to run before you say “done”
| Input | Expected | Why it matters |
|---|---|---|
| s = "" | 0 | Empty input. |
| s = "abba" | 2 | The left edge must never move backwards. |
| s = "a b" | 3 | Spaces are characters too. |
Answer the main question first, then take these on one at a time:
- What if you must return the substring, not its length?
- What if each character may appear at most twice?
- How would you handle a stream of characters?
Check your recording or written solution against this list:
- Moving the left edge backwards on a stale index
- Confusing a substring with a subsequence
- Rebuilding a set for every start index
This guide combines general interview-practice patterns with the public hiring material below. The practice prompt and coaching are PiriPiri AI editorial content, not official Google questions or answers.
Official sources reviewed 20 September 2026.