Lesson 21 of 107 5 min

The Sliding Window Pattern: Eliminating Redundant Calculations

Master the logic of Sliding Windows. Learn how to convert O(N^2) array problems into O(N) linear time using fixed and dynamic window strategies for MANG interviews.

Reading Mode

Hide the curriculum rail and keep the lesson centered for focused reading.

What is a Sliding Window?

Mental Model

Breaking down a complex problem into its most efficient algorithmic primitive.

The Sliding Window pattern is a specific optimization of the Two Pointers technique. It is used when you are asked to perform an operation on a contiguous sub-segment of an array or string.

In a naive approach, you would iterate through every possible subarray ($O(N^2)$) and calculate the property (sum, max, etc.) for that subarray. The "Magic" of the sliding window is that as the window moves from left to right, we don't recalculate everything inside it. We only care about the element entering the window and the element leaving it.

1. The Fixed Window Strategy

Use this when the length of the sub-segment is constant (e.g., "Find the max sum of any subarray of size K").

sequenceDiagram
    participant A as Array
    participant W as Window (Size 3)
    
    Note over A,W: Step 1: [1, 2, 3], 4, 5
    A->>W: Initial Sum: 6
    Note over A,W: Step 2: 1, [2, 3, 4], 5
    A->>W: Subtract 1, Add 4 (Sum: 9)
    Note over A,W: Step 3: 1, 2, [3, 4, 5]
    A->>W: Subtract 2, Add 5 (Sum: 12)

Fixed Window Template (Java)

public int fixedWindow(int[] nums, int k) {
    int currentSum = 0;
    // 1. Build the first window
    for (int i = 0; i < k; i++) currentSum += nums[i];
    int maxResult = currentSum;

    // 2. Slide the window
    for (int i = k; i < nums.length; i++) {
        currentSum += nums[i] - nums[i - k]; // O(1) update
        maxResult = Math.max(maxResult, currentSum);
    }
    return maxResult;
}

2. The Variable (Dynamic) Window Strategy

Use this when the window size changes based on a condition (e.g., "Find the smallest subarray with a sum $\ge$ S"). The dynamic window follows an "Expand until valid, Shrink until invalid" cycle.

graph TD
    Start[Right Pointer: Expand] --> Valid{Is Condition Met?}
    Valid -- No --> Start
    Valid -- Yes --> Record[Update Min/Max Result]
    Record --> Shrink[Left Pointer: Shrink]
    Shrink --> Valid

Variable Window Template (Java)

public int minWindow(int[] nums, int target) {
    int left = 0, sum = 0;
    int minLen = Integer.MAX_VALUE;

    for (int right = 0; right < nums.length; right++) {
        sum += nums[right]; // Expand
        
        while (sum >= target) { // While valid
            minLen = Math.min(minLen, right - left + 1); // Record
            sum -= nums[left]; // Shrink
            left++;
        }
    }
    return minLen == Integer.MAX_VALUE ? 0 : minLen;
}

3. The Staff-Level Interview Follow-Ups

Once you solve the basics, a Senior interviewer will pivot to these edge cases.

Follow-up 1: "What if the array contains negative numbers?"

This is the most common trap.

  • The Problem: If the array has negative numbers, adding an element (right++) doesn't necessarily increase the sum, and removing an element (left++) doesn't necessarily decrease the sum. The monotonic property breaks.
  • The Answer: "Sliding Window typically fails with negative numbers because the window sum is no longer monotonic. In this case, I would switch to a Prefix Sum + HashMap approach (similar to the subarray sum equals K problem) to maintain the running total and its frequency."

Follow-up 2: "HashMap vs. Frequency Array for String windows?"

  • The Answer: "If the character set is small and known (e.g., lowercase English letters), a new int[26] frequency array is significantly faster than a HashMap<Character, Integer>. It avoids object creation, prevents autoboxing, and provides better cache locality. I only use a HashMap if the input character set is large or unknown (e.g., full Unicode)."

4. The Verbal Interview Script (Communication)

Interviewer: "How would you optimize this subarray problem from $O(N^2)$?"

You: "Since the problem involves contiguous segments and we're looking for an optimal boundary, I'm considering a Sliding Window. The key intuition is that we can reuse the results of the previous window by only accounting for the elements that cross the left and right boundaries. This allows us to process the entire array in a single pass ($O(N)$). I'll use a right pointer to explore new data and a left pointer to contract the window once my target condition is satisfied, effectively 'squeezing' the window to find the optimal result."

5. Performance Trade-off Summary

Requirement Approach Complexity
Contiguous, No Negatives Sliding Window $O(N)$ Time, $O(1)$ Space
Contiguous, With Negatives Prefix Sum + Map $O(N)$ Time, $O(N)$ Space
Non-Contiguous Subsequence Two Pointers (Sorted) $O(N)$ Time, $O(1)$ Space
Non-Contiguous Subsequence Dynamic Programming $O(N^2)$ Time, $O(N)$ Space

6. Common Pitfalls to Avoid

  1. Off-by-One in result: Forgetting that the length of a window is right - left + 1.
  2. Invalidating too early: In variable windows, ensuring the while loop condition is correct so you don't shrink the window before recording a valid result.
  3. Resetting the state: Ensure that any state variables (like sum or count) are correctly updated in BOTH the expansion and contraction steps.

Key Takeaways

  • The Problem: If the array has negative numbers, adding an element (right++) doesn't necessarily increase the sum, and removing an element (left++) doesn't necessarily decrease the sum. The monotonic property breaks.
  • The Answer: "Sliding Window typically fails with negative numbers because the window sum is no longer monotonic. In this case, I would switch to a Prefix Sum + HashMap approach (similar to the subarray sum equals K problem) to maintain the running total and its frequency."
  • The Answer: "If the character set is small and known (e.g., lowercase English letters), a new int[26] frequency array is significantly faster than a HashMap<Character, Integer>. It avoids object creation, prevents autoboxing, and provides better cache locality. I only use a HashMap if the input character set is large or unknown (e.g., full Unicode)."

Want to track your progress?

Sign in to save your progress, track completed lessons, and pick up where you left off.