Skip to content

Beginner: foundations · Hashing, two pointers and sliding window · topic 14 of 61 · 30 min

Sliding window: fixed size

Explanation

A fixed-size window is a run of exactly k neighbouring items. Recomputing every window costs O(n × k). Sliding it is O(n): when the window moves one step, add the item that enters and remove the item that leaves. The same trick gives the best k-day sales total, moving averages, and the count of windows that are anagrams of a word.

What a window is

A window is a run of neighbouring items, described by where it starts and where it ends. A fixed-size window always holds exactly k items. Many questions ask about every window of size k: the best 7-day sales total, the average of every 24 hourly readings, or whether some stretch of a string is an anagram of a word. A list of n items has n − k + 1 windows of size k (when k ≤ n).

The slow way: recompute every window

Adding up k items for each of the n − k + 1 windows costs O(k) per window, so O(n × k) in total. With n = 100,000 days and k = 30 that is about 3 million additions; with k = 50,000 it is over a billion. sum(nums[i:i + k]) inside a loop is exactly this slow way, plus a copy of every slice.

The sliding trick

Two neighbouring windows share k − 1 items. When the window slides one step right, exactly one item enters (nums[i]) and one item leaves (nums[i − k]). So update the sum in O(1): window += nums[i] − nums[i − k]. Build the first window once, then slide. That is O(n) time in total and O(1) extra space.

Think of it like this: Looking out of a train window: as the train moves, one new tree appears at the right edge and one disappears at the left edge. You do not need to look at the whole view again to know what changed.
Window (indexes)EntersLeavesSum
0..2 = [2, 1, 5]——8
1..3 = [1, 5, 1]128 + 1 − 2 = 7
2..4 = [5, 1, 3]317 + 3 − 1 = 9
3..5 = [1, 3, 2]259 + 2 − 5 = 6
python
def max_window_sum(nums, k):          # assumes 1 <= k <= len(nums)
    window = sum(nums[:k])
    best = window
    for i in range(k, len(nums)):
        window += nums[i] - nums[i - k]    # one enters, one leaves
        best = max(best, window)
    return best

print(max_window_sum([2, 1, 5, 1, 3, 2], 3))   # Output: 9
The table above in code: the best 3-day total is 9.

Averages over a window

A moving average (also called a rolling average) is the average of each window: window_sum / k. It smooths noisy data, which is why dashboards show 7-day averages of sales or 24-hour averages of air quality. When the data are integers, keep the running sum as an integer and divide only when you report, so small rounding errors do not build up. Round only the final values, for example round(avg, 2).

Windows of counts: anagram windows

A window can hold more than a sum. To count the windows of s that are anagrams of p (same characters, same counts), keep a count map of the current window of size len(p). When the window slides, add 1 for the entering character and subtract 1 for the leaving one. Compare the window's map with p's map at each step.

Delete a key when its count drops to 0. A plain dict that still holds a zero entry is not equal to one without that key, so equal windows would look different:

python
window = {"a": 1, "b": 0}
print(window == {"a": 1})    # Output: False  (the zero entry still counts)
del window["b"]
print(window == {"a": 1})    # Output: True
Since Python 3.10, Counter treats zero counts as missing when comparing, but deleting is the safe habit in any language.

With a fixed alphabet, such as 26 lowercase letters, comparing two maps is O(26) = O(1), so the whole scan is O(n). A faster variant keeps a single number, "how many characters currently have the right count", and updates it as counts change.

Edge cases to settle first

  • k larger than n: there is no window at all. Decide what to return (None, [] or 0) and say it.
  • k = 0 or negative: usually invalid; handle it the same way.
  • Empty input: same as k > n.
  • Negative numbers are fine for fixed windows. The size is fixed, so you never have to decide when to shrink; that decision is what makes Topic 5 harder.

Common mistakes

  • Recomputing sum(nums[i:i + k]) for every window: O(n × k). Fix: slide with one add and one subtract.
  • Off-by-one in the leaving index. Fix: when nums[i] enters, nums[i − k] leaves; check it by hand with k = 1.
  • Starting best at 0, which is wrong when every window sum is negative. Fix: start best at the first window's sum.
  • Not handling k > len(nums): sum(nums[:k]) quietly sums a too-short list and returns a wrong answer. Fix: check k first.
  • Leaving zero counts in a dict window, so equal windows compare unequal. Fix: delete keys that reach 0.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Sliding window: fixed size · 1/8

Sliding window: fixed size

This lesson is about fixed-size sliding windows: runs of exactly k neighbouring items.

Prefer a video by a teacher? Find free videos on “sliding window fixed size maximum sum subarray of size k find all anagrams” on YouTube ↗

In real life: Smoothing air-quality readings

Air-quality dashboards, such as those built on government pollution data, often show the average of the most recent readings instead of one jumpy reading. Each new hour adds one reading and drops the oldest one, which is exactly a fixed-size sliding window. The example uses a window of 3 hours and made-up PM2.5 values to keep it short.

python
readings = [80, 95, 120, 150, 110, 90]   # hourly PM2.5 values (made-up)
k = 3
window = sum(readings[:k])
averages = [round(window / k, 2)]
for i in range(k, len(readings)):
    window += readings[i] - readings[i - k]
    averages.append(round(window / k, 2))
print(averages)
Shows [98.33, 121.67, 126.67, 116.67].

Practice (0/3 done)

Task 1 · Code · Python

sales[i] is a shop's sales on day i (it can be negative after returns). Write max_sum_k(sales, k) that returns the largest total of k CONSECUTIVE days. If k <= 0 or k > len(sales), return None. Use a sliding window: O(n) time, O(1) extra space. Example: max_sum_k([2, 1, 5, 1, 3, 2], 3) returns 9.

Task 2 · Code · Python

Write moving_averages(nums, k) that returns the average of every window of k consecutive numbers, from left to right, each rounded with round(value, 2). If k <= 0 or k > len(nums), return []. Keep a running sum (O(n) time). Example: moving_averages([1, 2, 3, 4, 5], 2) returns [1.5, 2.5, 3.5, 4.5].

Task 3 · Code · Python

Write count_anagram_windows(s, p) that returns how many windows of s of length len(p) are anagrams of p (same characters, same counts; case matters). p is never empty. Slide a window of counts: O(n) time for a fixed alphabet. Example: count_anagram_windows("cbaebabacd", "abc") returns 2 ("cba" at 0 and "bac" at 6).

Quick quiz

Question 1

1.The window has size k and nums[i] just entered. Which item leaves?

Question 2

2.n = 1,000,000 and k = 1,000. About how many steps do recomputing and sliding take?

Question 3

3.The window [4, 2, 7] has sum 13. The next item is 1 and k = 3. What is the next window sum?

Question 4

4.Why start best at the first window's sum instead of 0?

Question 5

5.How many windows of size k does a list of n items have (k ≤ n)?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

The window has size k and nums[i] just entered. Which item leaves?

Answer: nums[i − k]

The new window is i − k + 1 .. i, so the item just before it, nums[i − k], leaves.

n = 1,000,000 and k = 1,000. About how many steps do recomputing and sliding take?

Answer: About 10⁹ for recomputing, about 10⁶ for sliding

Recomputing costs about n × k; sliding does a constant amount of work per item.

The window [4, 2, 7] has sum 13. The next item is 1 and k = 3. What is the next window sum?

Answer: 10

13 − 4 (leaves) + 1 (enters) = 10, the sum of [2, 7, 1].

Why start best at the first window's sum instead of 0?

Answer: Because every window sum might be negative

If all sums are negative, starting at 0 would return 0, which is not the sum of any window.

How many windows of size k does a list of n items have (k ≤ n)?

Answer: n − k + 1

The window can start at 0, 1, …, n − k: that is n − k + 1 starts.

A loop with arr.indexOf inside it on the same array is…Related

Answer: O(n²)

indexOf is itself O(n).

From Data-structure questions in JavaScript

Why is the variable sliding window O(n) even with a while loop inside the for loop?Related

Answer: left only moves forward, so it moves at most n times in total

Across the whole run each item is added once and removed at most once.

From Sliding window: variable size

Which key puts exactly the anagrams of "listen" into one group AND can be used as a dict key?Related

Answer: "".join(sorted("listen"))

The sorted string is the same for all anagrams and is hashable. A set loses counts and is unhashable, a list is unhashable, and length groups unrelated words.

From Counting and grouping with hashing

n items and q range-sum queries. What is the total cost with a prefix array?Related

Answer: O(n + q)

O(n) to build once, then O(1) per query.

From Prefix sums and difference arrays

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 1 more topic in “Hashing, two pointers and sliding window” before its exam: Sliding window: variable size.
  2. Module 3 exam: Hashing, two pointers and sliding window · 14 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Stacks, queues and linked lists. 61 topics left in the course before the final exam.

← Previous: Two pointers