Given a string s, find the length of the longest substring that contains no repeating characters.
A substring is a contiguous run of characters within the string.
left directly past the previous occurrence, a common O(n) variant.Input: s = "abcabcbb" Output: 3 The longest substring without repeats is "abc", of length 3.
Input: s = "bbbbb" Output: 1 The best is "b", of length 1.
- 0 <= s.length <= 5 * 10^4 - s consists of English letters, digits, symbols and spaces.
A window s[left..right] is "valid" when it has no repeated character. Grow it by moving right; the moment the new character is already inside, slide left forward until the duplicate is gone. Every character enters and leaves the window at most once, so a single pass finds the longest valid window.
“Substring or subsequence?”
Substring — the characters must be contiguous.
“What counts as a repeat?”
Any character appearing more than once inside the current window makes it invalid.
“What about an empty string?”
The answer is 0 — there's no character to include.
I'll keep a window with no repeated characters, tracked in a set.
I extend the right edge each step; if the new character is already in the window, I shrink from the left until it isn't.
After each step the window is valid, so I record its length as a candidate answer.
Worked example — s = "abcabcbb"
right=0 a window "a" best 1 right=1 b window "ab" best 2 right=2 c window "abc" best 3 right=3 a dup! shrink -> window "bca" best 3 right=4 b dup! shrink -> window "cab" best 3 ... answer: 3
The window stays valid as long as new characters are fresh. You contract from the left exactly when the incoming character collides with one already inside.
Advancing left and deleting from the set is guaranteed to eventually remove the earlier occurrence of s[right], restoring uniqueness.
right and left both move only forward across the string, so despite the inner loop the total work is O(n).
| Extend from each start | Sliding window | |
|---|---|---|
| Idea | From each index, extend while unique | One window, shrink only on a duplicate |
| Time | O(n^2) | O(n) |
| Space | O(min(n, alphabet)) | O(min(n, alphabet)) |
The brute restarts the scan from every index; the window reuses the previous work by only ever moving both pointers forward. Full code is in the Approaches selector below.
Key takeaway
Keep a window with no repeats using a set. Extend right; whenever s[right] is already inside, advance left (removing characters) until it isn't, then record right - left + 1. Both pointers move forward only, so it's a single O(n) pass.
seen = set(); left = 0; best = 0
for right in 0 .. n-1:
while s[right] in seen: remove s[left]; left += 1
add s[right]; best = max(best, right - left + 1)
return best