The Idea: Slide, Don't Restart
Reuse the previous window's work with a running sum, and learn to spot window problems.
10 min, 0 of 3 activities solved
View cheatsheetGetting Python ready… examples can run in a moment.
Say you need the largest sum of any 3 consecutive numbers. The obvious way: for every start index, add up the next 3 numbers. That's O(n·k) work, and most of it is repeated.
Look at two neighbouring windows:
nums: [2, 1, 5, 1, 3, 2] k = 3
[2 1 5] sum 8
[1 5 1] 8 - 2 + 1 = 7
[5 1 3] 7 - 1 + 3 = 9
[1 3 2] 9 - 5 + 2 = 6
They share k − 1 numbers. When the window slides one step, only two things change: one number enters on the right and one leaves on the left. So you update the sum in O(1) instead of re-adding k numbers. That's the whole trick, and it makes the scan O(n).
Brute force vs sliding window
Same answer, about 90x less work. Try k = 500:
brute force does even more work, the sliding
version stays at about n steps.
How to recognise a window problem. Look for all three of these:
- The input is a sequence: an array or a string.
- The question is about a contiguous piece of it: a subarray or a substring.
- You want the longest / shortest / max / min / count of such pieces that satisfy some rule ("at most k distinct", "sum ≥ target", "no repeats").
Windows come in two flavours:
- Fixed size: "every window of length k". The window just slides. (This lesson.)
- Variable size: "the longest substring such that…". The window grows and shrinks. (Next lesson.)
The fixed-size template. Walk right over
every index. Add nums[right]. Once the window is
longer than k, remove nums[right - k]. Once it
has exactly k items (right >= k - 1), record an
answer. No special case for the first window.
Fixed window, one loop
The window covering right is
nums[right - k + 1 : right + 1]. Swap the sum for
a count (of vowels, of negatives…) and the same
loop answers many "every window of size k"
questions.
What does this print?
Which of these is a natural sliding window problem?
Count the good windows
Write count_good_windows(nums, k, threshold) that
returns how many windows of exactly k
consecutive numbers have an average ≥
threshold.
Use a running sum: each step adds one number and
removes one, so the whole scan is O(n). If
k > len(nums) there are no windows.
count_good_windows([2, 2, 2, 2, 5, 5, 5, 8], 3, 4)
-> 3 # [2,5,5], [5,5,5], [5,5,8]