Skip to Content
Course content

457: Whiteboard Practice: Sliding Window Techniques

Click on the "Edit" button in the top corner of the screen to edit your slide content.

If you've spent any time prepping for technical interviews or optimizing data processing pipelines, you've probably encountered a problem where you need to analyze a "chunk" of an array or string. The instinct for most of us—myself included, early in my career—is to just grab that chunk, process it, and then move one step over and do it all over again. It feels intuitive. But in the world of Big O, that intuition is usually a trap.

The temptation to recount everything

Let's say we're tasked with finding the maximum sum of any contiguous subarray of size k. If I'm glancing at this on a whiteboard, the "naive" approach is to loop through the list, and for every single index, slice the list to get the next k elements and sum them up. It looks something like this:

def max_sum_naive(arr, k):
    max_val = 0
    for i in range(len(arr) - k + 1):
        # We are summing k elements every single time
        current_sum = sum(arr[i:i+k]) 
        max_val = max(max_val, current_sum)
    return max_val

At first glance, this is clean. It's readable. But here is the problem: we are doing a massive amount of redundant work. If k is 1,000, we sum 1,000 elements, move one index to the right, and then sum 999 of those same elements again, plus one new one. We're basically treating every window as a brand new problem, ignoring the fact that the window at index i and the window at index i+1 are almost identical. In terms of complexity, this is O(n * k). If both n and k are large, your program is going to crawl.

Trading a loop for a simple subtraction

The "Sliding Window" technique is really just a way of saying, "Stop recalculating things you already know." Instead of re-summing the entire window, we just subtract the element that is falling out of the back of the window and add the element that is entering through the front. It’s a constant-time update regardless of how large k is.

I like to think of it as a train moving across the tracks. The train doesn't rebuild itself every time it moves an inch; it just gains a new piece of track at the front and leaves a piece behind at the back.

def max_sum_sliding(arr, k):
    if not arr or k > len(arr):
        return 0

    # Initial window: sum the first k elements once
    window_sum = sum(arr[:k])
    max_val = window_sum

    for i in range(len(arr) - k):
        # Subtract the element leaving (i) and add the element entering (i + k)
        window_sum = window_sum - arr[i] + arr[i + k]
        max_val = max(max_val, window_sum)
        
    return max_val

Now, look at the difference. We've moved from O(n * k) to O(n). We only traverse the list essentially once. Whether k is 5 or 5,000,000, the work we do inside that loop remains the same. That is the power of this pattern.

When the window needs to be flexible

The example above is a "fixed-size" window, but you'll often see "dynamic" windows in more complex problems—like finding the shortest subarray that sums to a specific target. In those cases, you don't have a constant k. Instead, you use two pointers (a left and a right). You expand the right pointer to grow your window until you meet a certain condition, and then you shrink the left pointer to see if you can still satisfy that condition with a smaller window.

It’s a bit more mental gymnastics to track the pointers, but the core philosophy remains: never recalculate what you can simply update. If you find yourself writing a sum() or a nested loop inside a loop that is processing a contiguous range, stop and ask yourself if a sliding window could replace it.




📋 Practical Task

Exercise: Finding the Smallest Window for a Target Sum

Your task is to implement a function smallest_subarray_with_sum(arr, target). Unlike the fixed-window example in the lesson, this window must be dynamic.

Write a function that takes a list of positive integers and a target sum. The function should return the length of the smallest contiguous subarray whose sum is greater than or equal to the target. If no such subarray exists, return 0.

Requirements:

  • Do not use nested loops that result in O(n^2) complexity. Aim for O(n) using the two-pointer sliding window technique.
  • The input list will only contain positive integers.

Example:
smallest_subarray_with_sum([2, 3, 1, 2, 4, 3], 7) should return 2 (because the subarray [4, 3] is the smallest that sums to at least 7).
smallest_subarray_with_sum([1, 2, 3], 10) should return 0.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.