Pattern

Sliding Window

Efficiently process contiguous subarrays and substrings by maintaining a window that slides through the data.

Roadmap

  1. What Is This Pattern?
  2. When to Use It
  3. Variant 1 — Fixed-Size Window
  4. Variant 2 — Variable-Size Window
  5. Variant 3 — Window with HashMap
  6. Template Code
  7. Common Problems
  8. Interactive Demo
  9. Complexity Analysis
  10. Key Takeaways
Step 01

What Is This Pattern?

The brute-force approach to subarray problems often recalculates everything from scratch for each position. The sliding window pattern avoids this by maintaining a "window" over a contiguous portion of the data and incrementally updating it as the window moves.

The Core Idea

Instead of recomputing the sum of each subarray from scratch, slide a window forward: add the new element entering on the right, remove the old element leaving on the left.

Array: window of size k=3
Step 1:
2
1
5
1
3
8
2
sum = 8
Step 2:
2
1
5
1
3
8
2
8 - 2 + 1 = 7
Step 3:
2
1
5
1
3
8
2
7 - 1 + 3 = 9
Step 4:
2
1
5
1
3
8
2
9 - 5 + 8 = 12
Step 5:
2
1
5
1
3
8
2
12 - 1 + 2 = 13
In window
Entering
Leaving
💡

Brute force: O(n * k) recomputes the sum for each window position. The sliding window does it in O(n) because each element enters and leaves the window exactly once.

Step 02

When to Use It

Look for these recognition signals in the problem statement. If you spot one, the sliding window pattern is very likely the intended approach.

"Find the longest/shortest subarray or substring with..."
A constraint on the window's contents, like a sum limit or character count.
"Maximum/minimum sum of k consecutive elements"
Fixed window size, sliding one element at a time.
"Contiguous sequence"
The answer must be a contiguous portion of the array or string.
"Character frequency constraints"
At most k distinct characters, all anagram occurrences, etc.

Not a sliding window? If the problem asks about non-contiguous subsequences, or if the data is not linear (like a tree or graph), sliding window does not apply. Also, if the array has negative numbers, a variable-size sum window may not work because shrinking does not always increase the sum.

Step 03

Variant 1 — Fixed-Size Window

Fixed Size

The window always contains exactly k elements. It slides one position to the right each step. Use this for problems like "maximum sum subarray of size k" or "moving average of last k values."

Template

int maxSumSubarray(int[] arr, int k) {
    int windowSum = 0, maxSum = Integer.MIN_VALUE;

    for (int i = 0; i < arr.length; i++) {
        windowSum += arr[i];               // add incoming element

        if (i >= k - 1) {                    // window is full
            maxSum = Math.max(maxSum, windowSum);
            windowSum -= arr[i - k + 1];   // remove outgoing element
        }
    }
    return maxSum;
}

Walkthrough: arr = [2, 1, 5, 1, 3, 8, 2], k = 3

i=2:
2
1
5
1
3
8
2
sum=8, max=8
i=3:
2
1
5
1
3
8
2
sum=7, max=8
i=4:
2
1
5
1
3
8
2
sum=9, max=9
i=5:
2
1
5
1
3
8
2
sum=12, max=12
i=6:
2
1
5
1
3
8
2
sum=13, max=13

Maximum sum of 3 consecutive elements = 13 at window [3, 8, 2].

Step 04

Variant 2 — Variable-Size Window

Variable Size

The window expands to the right unconditionally and contracts from the left when a condition is violated. This finds the longest/shortest valid subarray.

Template

int minSubarrayLen(int target, int[] arr) {
    int left = 0, windowSum = 0;
    int minLen = Integer.MAX_VALUE;

    for (int right = 0; right < arr.length; right++) {
        windowSum += arr[right];            // expand: always add right

        while (windowSum >= target) {          // shrink while valid
            minLen = Math.min(minLen, right - left + 1);
            windowSum -= arr[left];          // remove left element
            left++;
        }
    }
    return minLen == Integer.MAX_VALUE ? 0 : minLen;
}

Walkthrough: arr = [2, 3, 1, 2, 4, 3], target = 7

Find the shortest subarray with sum ≥ 7.

r=3:
2
3
1
2
4
3
sum=8 ≥ 7, len=4
shrink:
2
3
1
2
4
3
sum=6 < 7, stop
r=4:
2
3
1
2
4
3
sum=10 ≥ 7, len=4
shrink:
2
3
1
2
4
3
sum=7 ≥ 7, len=3
shrink:
2
3
1
2
4
3
sum=6 < 7, stop
r=5:
2
3
1
2
4
3
sum=9 ≥ 7, len=3
shrink:
2
3
1
2
4
3
sum=7 ≥ 7, len=2 *best*

Shortest subarray with sum ≥ 7 has length 2: the subarray [4, 3].

🎯

Why is this O(n)? Even though there is a while loop inside the for loop, each element is added at most once (when right advances) and removed at most once (when left advances). Total operations across all iterations: at most 2n.

Step 05

Variant 3 — Window with HashMap

HashMap / Counter

When you need to track the frequency of elements inside the window, combine the sliding window with a hash map. This is essential for string problems like "find all anagrams" or "minimum window substring."

Template: Find All Anagrams

List<Integer> findAnagrams(String s, String p) {
    List<Integer> result = new ArrayList<>();
    int[] need = new int[26], have = new int[26];

    for (char c : p.toCharArray()) need[c - 'a']++;

    int left = 0, matched = 0;
    for (int right = 0; right < s.length(); right++) {
        int c = s.charAt(right) - 'a';
        have[c]++;
        if (have[c] <= need[c]) matched++;  // useful match

        if (right - left + 1 > p.length()) {    // window too big
            int out = s.charAt(left) - 'a';
            if (have[out] <= need[out]) matched--;
            have[out]--;
            left++;
        }

        if (matched == p.length())             // all chars matched
            result.add(left);
    }
    return result;
}

Visual: s = "cbaebabacd", p = "abc"

Slide a window of size 3 and check if the frequency counts match "abc".

i=0:
c
b
a
e
b
a
b
a
c
d
anagram found
i=6:
c
b
a
e
b
a
b
a
c
d
anagram found

Anagrams of "abc" found at indices 0 and 6.

Step 06

Template Code

Here are the two fundamental templates you should memorize. Nearly every sliding window problem is a variation of one of these.

Fixed-Size Window

// Maximum sum of k consecutive elements
int windowSum = 0;
for (int i = 0; i < arr.length; i++) {
    windowSum += arr[i];                  // 1. Add incoming element

    if (i >= k - 1) {                      // 2. Window has k elements?
        maxSum = Math.max(maxSum, windowSum);  // 3. Update answer
        windowSum -= arr[i - k + 1];       // 4. Remove outgoing element
    }
}

Variable-Size Window

// Generic two-pointer sliding window
int left = 0;
for (int right = 0; right < arr.length; right++) {
    // 1. Expand: add arr[right] to window state

    while (windowIsInvalid()) {
        // 2. Shrink: remove arr[left] from window state
        left++;
    }

    // 3. Update answer with current valid window
    //    window = arr[left..right], length = right - left + 1
}
📝

Choosing between "shrink while invalid" vs "shrink while valid": If you want the longest valid window, shrink while invalid, then record. If you want the shortest valid window, shrink while valid and record during each shrink step.

Step 07

Common Problems

These are the classic LeetCode problems that use the sliding window pattern. They are listed in rough order of difficulty.

#3 Longest Substring Without Repeating Characters Medium
#209 Minimum Size Subarray Sum Medium
#438 Find All Anagrams in a String Medium
#567 Permutation in String Medium
#76 Minimum Window Substring Hard
#239 Sliding Window Maximum Hard
💡

Practice tip: Start with #209 (pure variable window + sum) and #3 (variable window + set). Once comfortable, tackle #76 which combines variable window with a frequency map and is considered one of the hardest medium/hard problems.

Step 08

Interactive Demo

Try both window variants with your own inputs. Step through to see exactly how the window moves.

⚙ Demo 1: Fixed-Size Window (Max Sum of k)



Press "Step →" or "Run All" to begin.

⚙ Demo 2: Variable-Size Window (Shortest Subarray with Sum ≥ Target)



Press "Step →" or "Run All" to begin.
Step 09

Complexity Analysis

Time
O(n)
Space
O(1) or O(k)

Why O(n) Time?

Fixed window: Each element is visited exactly once as right pointer sweeps the array. Each step does O(1) work (add one, subtract one). Total: O(n).

Variable window: The right pointer moves n times. The left pointer also moves at most n times total across all iterations (it never moves backward). So the inner while loop, summed across all outer iterations, runs at most n times. Total: O(n + n) = O(n).

Space: For pure sum-based windows, O(1). For hash map variants (character frequency), O(k) where k is the alphabet size or number of distinct elements in the pattern.

Amortized analysis: The key insight is that across the entire algorithm, each element is processed at most twice: once when the right pointer includes it, and once when the left pointer excludes it. This is why the nested loops still give linear time.

Step 10

Key Takeaways

01

Two variants, one idea. Fixed-size windows slide rigidly. Variable-size windows expand and contract. Both avoid redundant recalculation by updating incrementally.

02

O(n) from the two-pointer invariant. Each element enters the window once and leaves once. The inner shrink loop is not nested cost; it is amortized across the entire traversal.

03

Spot the pattern by keywords. "Contiguous subarray", "substring with at most k", "consecutive elements", "longest/shortest" are all strong signals for sliding window.

04

Combine with hash maps for string problems. When character frequencies matter, augment the window with a frequency counter. The window still slides the same way; you just track more state.

05

Watch for negative numbers. Variable-size sum windows assume that expanding the window can only increase the sum (or that shrinking can only decrease it). Negative numbers break this monotonicity, and you may need a different technique like prefix sums or deque-based approaches.