window hash set · holds exactly s[l..r] · dashed = best so far
public int lengthOfLongestSubstring(String s) { Set<Character> window = new HashSet<>(); // chars in s[l..r] int l = 0, best = 0; for (int r = 0; r < s.length(); r++) { while (window.contains(s.charAt(r))) { window.remove(s.charAt(l)); // shrink from the left l++; } window.add(s.charAt(r)); best = Math.max(best, r - l + 1); } return best;}
- l
- —
- r
- —
- s.charAt(r)
- —
- window
- []
- best
- 0
Why it works
- Brute force checks every substring for repeats: O(n³), or O(n²) with a fresh set per start index.
- Invariant: the window
s[l..r]never holds a repeat, and the set holds exactly its characters. Growrone step; ifs[r]is already inside, shrink from the left until it is gone. - Why O(n):
landronly move right, each at most n times, so the innerwhiledoes O(n) work in total. The set holds at most k distinct characters: O(min(n, k)) space. - Pitfall: on a repeat, do not restart the window at
r. In"dvdf"that loses"vdf". Drop characters from the left only until the old copy is gone. - Faster jumps: store each character's last index in a map and set
l = max(l, last[c] + 1), skipping the one-by-one removals. Still O(n), fewer steps.