--- title: 'Sliding Window' description: 'Two pointers plus incremental state between them.' --- ## The idea Two pointers that move the **same direction**, carrying state between them. Think of a caterpillar: - The head crawls forward and eats (expand right). - When the rule breaks, the tail pulls in until the rule holds again (contract left). The window is always a **contiguous** slice. You never rebuild it — you update the carried state as edges move. That is what makes it O(n). **The recipe:** 1. Expand right. Add the new element to your state. 2. Rule broken? Contract left until it holds. 3. Record the best window. Repeat. ## The picture ```mermaid flowchart TD A["a b c a b c
[a] window = a"] --> B["[a b] expand → ab"] B --> C["[a b c] expand → abc, best = 3"] C --> D["a [b c a] 'a' repeats → contract, then expand"] D --> E["a b [c a b] keep sliding, best stays 3"] style C fill:#2e7d32,color:#fff ``` ## Longest Substring Without Repeating (LC 3) State = a set of chars in the window. Repeat found? Shrink from the left until it is gone. ```python def length_of_longest_substring(s: str) -> int: window = set() left = 0 best = 0 for right, c in enumerate(s): while c in window: # rule broken window.remove(s[left]) # contract left left += 1 window.add(c) # expand right best = max(best, right - left + 1) return best ``` ## Best Time to Buy and Sell (LC 121) — the hidden window Looks like a stock problem. It is a window problem. Left = cheapest buy so far. Right = today. Carry one number: the min price. ```python def max_profit(prices: list[int]) -> int: min_price = prices[0] best = 0 for p in prices[1:]: best = max(best, p - min_price) min_price = min(min_price, p) return best ``` ## Character Replacement (LC 424) — window with a budget Rule: window is valid if `window size − count of top letter ≤ k`. That many replacements fix the window. Carry a frequency map. ```python from collections import defaultdict def character_replacement(s: str, k: int) -> int: count = defaultdict(int) left = 0 best = 0 top = 0 # highest letter count seen for right, c in enumerate(s): count[c] += 1 top = max(top, count[c]) if (right - left + 1) - top > k: # over budget count[s[left]] -= 1 # contract exactly one step left += 1 best = max(best, right - left + 1) return best ``` ## When the window fails Sliding window needs a one-way rule: **growing can only hurt, shrinking can only help.** Negative numbers break this — a bigger window can flip from bad to good. That is when you reach for prefix sum + hashmap (LC 560) instead. Say this decision out loud in the interview. ## Complexity | | Time | Space | |---|---|---| | All patterns above | O(n) — each index enters and leaves once | O(1) or O(alphabet) | ## Close-out ritual Before you submit, say out loud: 1. Time and space complexity — note each element enters and leaves the window at most once. 2. One edge case trace: empty string, all same char, or k larger than the string. ## Plan problems **A-set:** LC 121 · 3 · 424 · 567 · 76 **B-set:** LC 209 · 1004 · 643