Here's a year of daily revenue — 365 numbers. One question: which single week — seven consecutive days — brought in the most?
The obvious approach: for each starting day, add up its seven days, keep the best. Simple. But look at what happens between two neighboring weeks — days 2–8 and days 3–9. They share six of the seven days. You add those six up… then add almost exactly the same six up again… and again, for every starting position. You are re-adding the same numbers thousands of times.
For 365 days, who cares. For a million sensor readings with a window 10,000 wide, that's ten billion additions — almost all of it repeating work you already did. There's a fix so simple it feels like a trick, and it's one of the most reusable patterns in all of programming. Let's get it.
A for-loop is all you need. This is the natural next step after two pointers — same idea, pointers moving the same direction now.
The brute force, and the waste hiding in it
Fix a start, add the next k, remember the best:
// O(n·k): re-sum every window from scratch
let best = -Infinity;
for (let start = 0; start + k <= n; start++) {
let sum = 0;
for (let i = start; i < start + k; i++) sum += a[i];
best = Math.max(best, sum);
}Correct, and slow. The waste is specific and visible: every window overlaps the next one by k − 1 elements. We throw away a perfectly good sum and rebuild it from scratch, even though 99% of it didn't change.
So don't rebuild. Slide. When the window steps one place to the right, exactly two things change: one element falls off the left, one element joins on the right. Everything in between is identical. So:
new sum = old sum − (the element that left) + (the element that entered)
Two operations. Per step. No matter how wide the window is. The window glides across the array carrying its running sum, paying a flat cost at each step instead of re-summing the whole thing. That's the sliding window.
Watch it glide
A window of width 3 slides across. Watch the sum update by a single subtraction and a single addition each step — it never re-adds the whole window:
The running total never restarts; it just adjusts. That one subtraction-and-addition is the entire O(n·k) → O(n) win. Try it yourself in the box: change the window size, throw in negatives, lengthen the array — the two-operation slide holds no matter what.
The whole thing
The entire technique is that one line: sum += a[i] - a[i - k]. Add the newcomer, drop the one that aged out. One pass, O(n) time, O(1) space — and the window's size never enters the cost.
What to take away
- When to reach for it: any contiguous "window" question — the best, the sum, the average over a fixed span of a sequence.
- Complexity: O(n) time, O(1) space. The window's width is free.
- The bigger family — a window that breathes: the real power shows up when the window isn't a fixed size. "Smallest window whose sum reaches S" — grow the right edge until the condition holds, then shrink the left edge while it still holds. "Longest stretch with no repeats" — same dance. That's a variable sliding window.
- The link back to two pointers: a fixed window is two pointers locked
kapart; a variable window is two pointers moving independently, the same direction. In post #1 they walked toward each other; here they chase each other rightward. Same family, different choreography.
When a window slides by one, almost nothing changes — so don't recompute it. Subtract what left, add what entered. The window's size stops mattering, and O(n·k) quietly collapses to O(n).
Try it yourself
Five problems. The first is this exact fixed window; the rest open the door to the variable window, where the pattern really earns its reputation.
- Maximum Average Subarray I — LeetCode 643. The fixed window, exactly as above — just divide by k at the end. The canonical first sliding-window problem.
- Minimum Size Subarray Sum — LeetCode 209. Your first variable window: grow the right edge until the sum reaches the target, then shrink from the left while it still holds. Track the smallest width seen.
- Longest Substring Without Repeating Characters — LeetCode 3. The famous one. Slide a window over a string; when a repeat enters, shrink from the left until it's gone. A set tracks what's inside.
- Sliding Window Maximum — LeetCode 239. A fixed window again, but now you need the maximum inside it at every step. The naive scan is O(n·k) all over again; a monotonic deque gets you back to O(n).
- Minimum Window Substring — LeetCode 76. The boss fight. A variable window over a string that must contain every required character, with counts — grow to satisfy, shrink to minimize. Master this and you've mastered the pattern.
Once "the window slides, so only the edges change" is in your bones, you start seeing it everywhere — strings, streams, time ranges, rate limiters. It's the same instinct behind Kadane and two pointers: refuse to redo work the problem already did for you. The fastest code usually isn't clever. It just won't repeat itself.