Longest Substring Without Repeating
Find the longest substring with all unique characters — sliding window with a last-seen map, O(n) time.
intermediate3 min read
- dsa
- sliding-window
- interview
- Meta
- Amazon
- Microsoft
The problem
Given a string s, return the length of the longest substring (contiguous) that contains no repeating characters.
Input: s = "abcabcbb"
Output: 3 // "abc"
Input: s = "bbbbb"
Output: 1 // "b"
Input: s = "pwwkew"
Output: 3 // "wke"
Mental model: expand a window [left, right]. When you hit a duplicate inside the window, jump left past the previous occurrence.
Brute force
For every start index, grow right until a repeat. Use a set per start.
function lengthOfLongestSubstringBrute(s: string): number {
let best = 0;
for (let i = 0; i < s.length; i++) {
const seen = new Set<string>();
for (let j = i; j < s.length; j++) {
if (seen.has(s[j])) break;
seen.add(s[j]);
best = Math.max(best, j - i + 1);
}
}
return best;
}
| Time | O(n²) |
| Space | O(min(n, Σ)) charset size |
Optimal: sliding window + last index
Keep left as the start of the current unique window. Map each char to its last index. On a hit with index ≥ left, set left = last + 1. Always update best with right - left + 1.
function lengthOfLongestSubstring(s: string): number {
const last = new Map<string, number>();
let left = 0;
let best = 0;
for (let right = 0; right < s.length; right++) {
const ch = s[right];
if (last.has(ch) && last.get(ch)! >= left) {
left = last.get(ch)! + 1;
}
last.set(ch, right);
best = Math.max(best, right - left + 1);
}
return best;
}
| Time | O(n) |
| Space | O(min(n, Σ)) |
Walk "pwwkew"
| right | ch | left | window | best |
|---|---|---|---|---|
| 0 | p | 0 | p | 1 |
| 1 | w | 0 | pw | 2 |
| 2 | w | 2 | w | 2 |
| 3 | k | 2 | wk | 2 |
| 4 | e | 2 | wke | 3 |
| 5 | w | 3 | kew | 3 |
Edge cases
- Empty string → 0
- All unique →
s.length - All same char → 1
- Spaces and punctuation count as characters
- Unicode: JS strings are UTF-16 code units; for full code points use careful iteration if required
Common bugs
- Moving
leftonly by one when the previous occurrence is far left — you must jump - Not checking
last.get(ch) >= left(stale indices outside the window) - Returning the substring when the problem asks for length (or vice versa)
- Using a set and forgetting to shrink from the left correctly
Interview delivery
- Restate: longest contiguous unique chars.
- Brute O(n²), then window.
- Code one-pass map.
- Trace a string with an internal duplicate.
- Complexity O(n) / O(Σ).