Introduction
In the previous post, we learned the Two Pointer technique. The Sliding Window technique is a specific, powerful variation of the same-direction two-pointer approach.
Imagine looking at a long ruler through a magnifying glass that only shows exactly 3 inches of the ruler at a time. If you want to see the next 3 inches, you don’t pick up the magnifying glass and place it down again — you simply slide it to the right. As you slide it 1 inch, one old number leaves your view, and one new number enters.
This is exactly how the Sliding Window technique works on arrays and strings. It is the perfect tool for any problem asking for a “contiguous sub-array” or “sub-string” that meets certain criteria.
The Two Patterns
There are two main types of sliding window problems:
- Fixed-Size Window: The window size never changes (e.g., “find the max sum of exactly $k$ elements”).
- Dynamic Window: The window expands and shrinks to satisfy a condition (e.g., “find the smallest sub-array with a sum $\ge$ target”).
Pattern 1: Fixed-Size Window
Problem: Given an array of integers and a number $k$, find the maximum sum of any contiguous sub-array of size $k$.
Brute-Force Approach — $O(n \times k)$
int maxSum = 0;
for (int i = 0; i <= arr.length - k; i++) {
int currentSum = 0;
for (int j = i; j < i + k; j++) { // recalculate the entire window
currentSum += arr[j];
}
maxSum = Math.max(maxSum, currentSum);
}
This is painfully slow because we recalculate the overlapping parts over and over again.
Sliding Window Approach — $O(n)$
Instead of recalculating, we just update the sum. When the window slides right by one position:
- We add the new element entering the window on the right.
- We subtract the old element leaving the window on the left.
Walkthrough
Find the max sum of size $k = 3$ in [2, 1, 5, 1, 3, 2].
| Window | Elements | Entering | Leaving | Current Sum | Max Sum |
|---|---|---|---|---|---|
[2, 1, 5] | 2, 1, 5 | — | — | 8 | 8 |
[1, 5, 1] | 1, 5, 1 | +1 | -2 | 8 + 1 - 2 = 7 | 8 |
[5, 1, 3] | 5, 1, 3 | +3 | -1 | 7 + 3 - 1 = 9 | 9 |
[1, 3, 2] | 1, 3, 2 | +2 | -5 | 9 + 2 - 5 = 6 | 9 |
Max Sum: 9 ✅
Java Implementation
public class FixedSlidingWindow {
public static int maxSumSubarray(int[] arr, int k) {
if (arr.length < k) return 0; // edge case
int maxSum = 0;
int windowSum = 0;
// Step 1: Calculate the sum of the FIRST window
for (int i = 0; i < k; i++) {
windowSum += arr[i];
}
maxSum = windowSum;
// Step 2: Slide the window across the rest of the array
for (int i = k; i < arr.length; i++) {
// Add the new element, subtract the element left behind
windowSum += arr[i] - arr[i - k];
maxSum = Math.max(maxSum, windowSum);
}
return maxSum;
}
public static void main(String[] args) {
int[] data = {2, 1, 5, 1, 3, 2};
System.out.println(maxSumSubarray(data, 3)); // Output: 9
}
}
Pattern 2: Dynamic Window
Problem: Given an array of positive integers and a target sum, find the length of the smallest contiguous sub-array whose sum is $\ge$ target.
Because the window size is not fixed, we use two pointers: left and right.
- Expand the window by moving
rightand adding to the sum until the condition is met. - Shrink the window by moving
leftand subtracting from the sum to see if we can find a smaller window that still meets the condition.
Walkthrough
Target = 7, Array = [2, 3, 1, 2, 4, 3]
| left | right | Window | Sum | Condition (≥ 7) | Action | Min Length |
|---|---|---|---|---|---|---|
| 0 | 0 | [2] | 2 | ❌ | Expand right | ∞ |
| 0 | 1 | [2, 3] | 5 | ❌ | Expand right | ∞ |
| 0 | 2 | [2, 3, 1] | 6 | ❌ | Expand right | ∞ |
| 0 | 3 | [2, 3, 1, 2] | 8 | ✅ | Record len (4), Shrink left | 4 |
| 1 | 3 | [3, 1, 2] | 6 | ❌ | Expand right | 4 |
| 1 | 4 | [3, 1, 2, 4] | 10 | ✅ | Record len (4), Shrink left | 4 |
| 2 | 4 | [1, 2, 4] | 7 | ✅ | Record len (3), Shrink left | 3 |
| 3 | 4 | [2, 4] | 6 | ❌ | Expand right | 3 |
| 3 | 5 | [2, 4, 3] | 9 | ✅ | Record len (3), Shrink left | 3 |
| 4 | 5 | [4, 3] | 7 | ✅ | Record len (2), Shrink left | 2 |
| 5 | 5 | [3] | 3 | ❌ | Right reaches end | 2 |
Smallest length: 2 (the sub-array is [4, 3]). ✅
Java Implementation
public class DynamicSlidingWindow {
public static int minSubArrayLen(int target, int[] arr) {
int minLength = Integer.MAX_VALUE;
int windowSum = 0;
int left = 0;
// 'right' expands the window continuously
for (int right = 0; right < arr.length; right++) {
windowSum += arr[right];
// When the condition is met, try to shrink from the left
while (windowSum >= target) {
minLength = Math.max(minLength, right - left + 1);
// Subtract the element going out and move left forward
windowSum -= arr[left];
left++;
}
}
return minLength == Integer.MAX_VALUE ? 0 : minLength;
}
public static void main(String[] args) {
int[] data = {2, 3, 1, 2, 4, 3};
System.out.println(minSubArrayLen(7, data)); // Output: 2
}
}
Why is this $O(n)$? Wait, there is a
whileloop inside aforloop — isn’t that $O(n^2)$? No! Look closely at theleftpointer. It only moves forward. It starts at index 0 and at most goes to index $N$. Therefore, each element in the array is added exactly once and subtracted exactly once. Total operations: $2N$, which is $O(n)$.
How to Spot a Sliding Window Problem
You should immediately think of Sliding Window if the problem contains these keywords:
- “Contiguous sub-array” or “sub-string”
- “Maximum / Minimum / Longest / Shortest”
- “Sum / Character count / Distinct elements”
Common Data Structures to Pair With
If the problem involves strings (like “longest substring without repeating characters”), you will almost always use a HashMap or HashSet inside your window to keep track of character frequencies.
When to Use / When NOT to Use
| ✅ Use When | ❌ Avoid When |
|---|---|
| Asking for a contiguous sequence | Asking for a subsequence (elements don’t need to be next to each other) |
| Looking for max/min metric of a fixed size | Array contains negative numbers and asks for a target sum (dynamic window breaks here because adding a negative number shrinks the sum — use prefix sums instead) |
| Looking to satisfy a condition with the longest/shortest contiguous sequence |
Practice Problems
- Maximum Average Subarray I – LeetCode #643 — Classic fixed-size window.
- Minimum Size Subarray Sum – LeetCode #209 — The dynamic window problem we just solved.
- Longest Substring Without Repeating Characters – LeetCode #3 — A must-know string problem pairing sliding window with a HashSet.
- Permutation in String – LeetCode #567 — Fixed window + frequency HashMap.
What’s Next?
We just mastered looking across data structures sequentially. Next, we will look at two foundational data structures that strictly control how and where you access data: Stacks & Queues — Core Operations.