You know you need a Sliding Window. But do you need a Fixed window or a Dynamic one?
Choosing the wrong variant is like trying to fit a square peg in a round hole. The logic for expanding and shrinking is completely different.
In this guide, we will break down the two flavors of Sliding Window, provide code templates for each, and give you a decision matrix to solve any problem.
TL;DR — Fixed vs Dynamic
- Fixed Window: Size is constant (). Move
leftandrighttogether.- Use for: "Subarray of size K", "Anagrams".
- Dynamic Window: Size changes. Grow
right, shrinkleftto satisfy condition.- Use for: "Longest substring", "Smallest subarray sum".
Definitions
Fixed Window
The window size is constant. You slide the window one step at a time.
- Movement:
rightmoves 1 step,leftmoves 1 step. - Size: Always exactly .
Dynamic Window
The window grows and shrinks based on a condition.
- Movement:
rightmoves to find a valid window.leftmoves to optimize it (shrink). - Size: Variable (from 0 to ).
Which problems require fixed window?
Use a Fixed Window when the problem explicitly states a size constraint or asks for a statistic over a specific range.
- "Find the maximum sum of a subarray of size K."
- "Find all anagrams of string P in string S." (Window size = length of P).
- "Calculate the moving average of the last K elements."
Which problems need dynamic window?
Use a Dynamic Window when the problem asks for the "longest" or "shortest" subarray/substring that satisfies a condition.
- "Longest substring without repeating characters."
- "Smallest subarray with sum S."
- "Longest subarray with at most K distinct characters."
Decision matrix: problem clues → window type
| Problem Clue | Window Type |
|---|---|
| "Subarray of size K" | Fixed |
| "Longest / Shortest" | Dynamic |
| "At most K distinct..." | Dynamic |
| "Permutation / Anagram" | Fixed (Size = Pattern Length) |
| "Minimum window containing..." | Dynamic |
Code templates for both types
1. Fixed Window Template
function fixedSlidingWindow(nums: number[], k: number) {
let currentSum = 0;
// 1. Initialize first window
for (let i = 0; i < k; i++) currentSum += nums[i];
let maxSum = currentSum;
// 2. Slide window
for (let right = k; right < nums.length; right++) {
currentSum += nums[right]; // Add new
currentSum -= nums[right - k]; // Remove old
maxSum = Math.max(maxSum, currentSum);
}
return maxSum;
}2. Dynamic Window Template
function dynamicSlidingWindow(nums: number[], target: number) {
let left = 0, currentSum = 0, minLen = Infinity;
for (let right = 0; right < nums.length; right++) {
// 1. Expand
currentSum += nums[right];
// 2. Shrink while condition is met (or broken, depending on problem)
while (currentSum >= target) {
minLen = Math.min(minLen, right - left + 1);
currentSum -= nums[left];
left++;
}
}
return minLen;
}Performance considerations & pitfalls
- Mixing Logic: Don't try to use a
whileloop for shrinking in a Fixed Window problem. It's unnecessary complexity. - Initialization: Fixed windows often require a separate loop to initialize the first elements. Don't forget this, or you'll have an off-by-one error.
- Empty Inputs: Dynamic windows handle empty inputs naturally. Fixed windows need a check:
if (nums.length < k) return 0;.
Summary
- Fixed: Lock the size. Slide both pointers together.
- Dynamic: Caterpillar movement. Expand
right, shrinkleft.
Next Step:
Now that you can choose the window type, learn how to distinguish Sliding Window from its close cousin in Sliding Window vs Prefix Sum.
Ready to Practice This Pattern?
Apply this pattern with LeetCopilot's AI-powered hints, notes, and mock interviews. Transform your coding interview preparation today.
