Longest Substring Without Repeating Characters is the classic introduction to the sliding window. It teaches a pattern that turns many "longest / shortest substring" problems from O(n²) into a clean single pass.
Problem. Given a string s, find the length of the longest substring that contains no repeated
character. A substring is a run of characters that are next to each other.
Example: s = "abcabcbb" → answer 3 (the substring "abc"). After that, every length-3 window hits a
repeat, so 3 is the best we can do.
The slow way first
The obvious idea: try every starting point, and from each one extend as far as you can without a repeat. That is O(n²) — for a long string it is far too slow, and it redoes work the previous start already proved.
The better question: can I keep one window and slide it, instead of restarting? Yes. As the right edge moves forward, the only thing that can break the "no repeat" rule is the new character. If it causes a duplicate, we just shrink the left edge until the duplicate is gone.
The idea: a window that never repeats
Keep a window [L, R] and a set of the characters inside it. Move R forward one step at a time:
- If
s[R]is not in the set, add it — the window grew, so update the best length. - If
s[R]is in the set, removes[L]and moveLright, again and again, until the duplicate is gone. Then adds[R].
Because each character enters the set once and leaves at most once, both pointers only ever move right. That is what makes it O(n).
The key insight: the window always holds a valid (no-repeat) substring, so its length at every step is a candidate answer.
Walk through it
Step through the animation. R scans left to right; the window set shows what is inside. When R hits a character that is already in the window ("a" at index 3, then "b", then "c"...), L jumps forward to drop the old copy. The best length locks in at 3 early and never grows.
Pseudocode
window = empty set # characters currently inside [L, R]
best = 0
L = 0
for R from 0 to len(s) - 1:
while s[R] is already in window:
remove s[L] from window # shrink from the left
L = L + 1
add s[R] to window
best = max(best, R - L + 1) # window length is a candidate
return bestThe Python solution
def length_of_longest(s):
window = set()
best = 0
L = 0
for R in range(len(s)):
while s[R] in window:
window.remove(s[L])
L += 1
window.add(s[R])
best = max(best, R - L + 1)
return bestwindowis a set of the characters in the current window, sos[R] in windowis an O(1) check.Lis the left edge;R(the loop variable) is the right edge.- The
whileloop (lines 6–8) is the shrink: as long as the new character is already inside, we drop the leftmost character and moveLright. This is what makes the window valid again. - After shrinking,
window.add(s[R])brings the new character in. R - L + 1is the current window length, and we keep the largest one inbest.
Complexity
| Case | Time | Notes |
|---|---|---|
| Brute force (every substring) | O(n²) (slow) | restart from each index |
| Sliding window (this solution) | O(n) (moderate) | each pointer only moves right |
O(k) (moderate)Both L and R move forward at most n times total, so the work is O(n). The extra space is O(k), where k is the number of distinct characters that can fit in the window (at most the alphabet size).
When this pattern shows up
Whenever a problem asks for the longest or shortest run that satisfies some rule (no repeats, at most K distinct, sum ≤ target), reach for a sliding window. Grow the right edge; when the rule breaks, shrink the left edge. "Longest substring with at most K distinct characters" and "minimum window substring" are the same move.
Shrink with a while loop, not a single if. One repeated character might require removing several
characters from the left before the window is valid again. A single if would leave a duplicate inside.
Practice
For s = 'abcabcbb', when R reaches the second 'a' (index 3), what does L do, and does best change?
1. Why is the sliding-window solution O(n) and not O(n²)?
2. What does the set (window) hold?
3. Why must shrinking use a while loop instead of a single if?
4. What is the current window length, given L and R?