Skip to content
← All posts

Maximum Average Subarray I: Fixed-Size Sliding Window

4 min read
leetcodeproblemeasyarrayssliding-window

Think about checking the weather forecast. You want to know which four consecutive days had the highest average temperature. You would not re-add all four temperatures from scratch every time you shift the window by one day. You would drop the oldest day, add the newest, and update your running total. That is exactly what LeetCode 643, Maximum Average Subarray I, asks you to do with an array of numbers.

Given an integer array nums and an integer k, find the contiguous subarray of length k that has the maximum average value, and return that average.

10121-52-6350435best window (k=4)sum = 51, avg = 12.75
nums = [1, 12, -5, -6, 50, 3], k=4. The window [12, -5, -6, 50] at indices 1-4 has sum 51 and average 12.75, the maximum possible.

Why this problem matters

This is one of the cleanest introductions to the fixed-size sliding window pattern. Unlike variable-size sliding windows (where the window grows and shrinks), the window here is always exactly k elements wide. That makes the logic simpler and gives you a solid foundation before tackling harder variants.

Fixed-size sliding windows show up constantly in real-world engineering: rolling averages for monitoring dashboards, moving averages in financial data, and smoothing signals in sensor data. If you can implement this pattern cleanly, you have a building block that transfers directly to production code, not just interviews.

The approach

The brute force solution computes the sum of every possible window of size k from scratch. That means for each of the n - k + 1 starting positions, you add up k elements. The total work is O(n * k), which is wasteful because consecutive windows overlap by k - 1 elements.

The fixed-size sliding window avoids this redundancy. You compute the sum of the first window once. Then, for each subsequent position, you subtract the element leaving the window (the leftmost) and add the element entering (the new rightmost). Each slide costs O(1), so the total is O(n).

The solution

def findMaxAverage(nums, k):
    window_sum = sum(nums[:k])
    best = window_sum

    for i in range(k, len(nums)):
        window_sum += nums[i] - nums[i - k]
        best = max(best, window_sum)

    return best / k

The key insight is that you never need to recompute the full window sum. When the window slides one position right, you add the new element and subtract the old one. This single add-and-subtract step replaces an entire inner loop, turning O(n * k) into O(n).

Step-by-step walkthrough

Let's trace through nums = [1, 12, -5, -6, 50, 3] with k = 4. The window slides from left to right, one position at a time.

Step 1: First window covers indices 0-3. Compute the initial sum.

10121-52-6350435sum=2, avg=0.50best avg = 0.50

sum = 1 + 12 + (-5) + (-6) = 2. Average = 2 / 4 = 0.50. This is our first window, so it is the best so far.

Step 2: Slide right. Remove nums[0]=1, add nums[4]=50.

10121-52-6350435sum=51, avg=12.75best avg = 12.75

sum = 2 - 1 + 50 = 51. Average = 51 / 4 = 12.75. New best! Much better than 0.50.

Step 3: Slide right. Remove nums[1]=12, add nums[5]=3.

10121-52-6350435sum=42, avg=10.50best avg = 12.75

sum = 51 - 12 + 3 = 42. Average = 42 / 4 = 10.50. Not better than 12.75. Final answer: 12.75.

After checking all three window positions, the best sum is 51 (from the window [12, -5, -6, 50]), giving an average of 12.75.

Complexity analysis

ApproachTimeSpace
Brute forceO(n * k)O(1)
Sliding windowO(n)O(1)

Time: O(n). We make one pass through the array. Each element is visited exactly once.

Space: O(1). We only store the running sum and the best sum. No extra data structures.

Edge cases to watch for

  • k equals the array length: There is only one window, so the answer is the average of the entire array. The code handles this naturally because the loop body never executes.
  • All negative numbers: The algorithm still works correctly. The "maximum average" will be the least negative average. Because we track the best sum (which can be negative), no special handling is needed.
  • All same values: Every window has the same sum, so any window is valid. The code returns the correct average on the first iteration.

The building blocks

This problem decomposes into one core pattern.

Fixed-size sliding window

Unlike the variable-size sliding window in problems like Minimum Size Subarray Sum, there is no shrinking step here. The window is always exactly k wide. You compute the initial window, then slide it forward one element at a time with a single add-and-subtract.

window_sum = sum(nums[:k])

for i in range(k, len(nums)):
    window_sum += nums[i] - nums[i - k]

This same fixed-size template appears in other problems: Find All Anagrams in a String uses a fixed window with frequency matching instead of a sum. Sliding Window Maximum uses a fixed window with a monotonic deque to track the max. The window mechanics stay the same. Only the state you track inside the window changes.

Recognizing whether a problem calls for a fixed-size or variable-size window is the first decision point. If k is given and constant, you almost certainly want the fixed-size template. If you need to find the optimal window size, you want the variable-size (expand and shrink) template.

From understanding to recall

You have seen the pattern and traced through the example. But will you remember the details a month from now? Will you recall that you track the sum (not the average) during the loop, and only divide at the end? These small details are where bugs hide under interview pressure.

Spaced repetition closes the gap between understanding and recall. Instead of solving this problem once and moving on, you revisit it at increasing intervals. Each time you write the code from scratch. After a few repetitions, the fixed-size sliding window template becomes automatic, not something you need to re-derive.

Related posts