"Two adjacent windows over an array share almost all their elements. Recomputing each from scratch throws that overlap away. A sliding window keeps it — and that's the whole O(n²) → O(n) win."
The Wasteful Way, and the Fix
Say you want the maximum sum of any k consecutive elements. The naive approach: for each starting position, add up its k elements. That's n windows × k additions = O(n·k), which is O(n²) when k grows with n. But look at two neighboring windows — they overlap in all but one element on each side. The brute force re-adds that shared middle every single time.
The sliding window fixes this: compute the first window's sum once, then slide by adding the element entering on the right and subtracting the element leaving on the left. Each slide is O(1), so the whole scan is O(n). You never recompute the overlap — you just adjust at the edges. It's the same instinct as amortized analysis and prefix sums: don't redo work you already did.
Two Flavors of Window
- Fixed-size window — the window is always
kwide; it just slides. Used for "max/min/average of every k-length run." - Variable-size window — the two ends move independently to satisfy a condition. Grow the right edge until the window is "valid enough," then shrink the left edge while it stays valid. Used for "longest substring with no repeats," "smallest subarray with sum ≥ target." Both edges still only move forward, so it's still O(n) total even though it looks like two loops.
Why the Variable Window Is Still O(n)
The variable window looks like a nested loop — an outer pointer and an inner shrink loop — so people assume O(n²). The trick is that the left pointer never moves backward. Across the whole run, the right pointer advances n times and the left pointer advances at most n times. Total moves ≤ 2n. Counting total pointer movement rather than nesting is how you see it's O(n). This is the same amortized reasoning from the Complexity track, applied to a loop shape.