Sliding Window (Variable Size)
Builds on Two Pointers. Use this for contiguous subarrays where you need to track a "state" (sum, frequency, etc.).
Recognition
- Contiguous subarray/substring with a constraint on sum, uniqueness, or frequency.
- You can grow a right edge and shrink a left edge while maintaining window state.
When not to use it
Do not force this pattern when the input is unordered and hashing is enough.
Avoid coding the template before naming the invariant you need to preserve.
Logic template
Python
def sliding_window(arr):
left = 0
state = 0 # Can be a sum, a dictionary, etc.
res = 0
for right in range(len(arr)):
# 1. Add right element to state
state += arr[right]
# 2. While condition is violated, shrink from left
while state > target:
state -= arr[left]
left += 1
# 3. Update result
res = max(res, right - left + 1)
return resJavaScript
function slidingWindow(arr) {
let left = 0;
let state = 0; // Can be a sum, an object/map, etc.
let res = 0;
for (let right = 0; right < arr.length; right++) {
// 1. Add right element to state
state += arr[right];
// 2. While condition is violated, shrink from left
while (state > target) {
state -= arr[left];
left++;
}
// 3. Update result
res = Math.max(res, right - left + 1);
}
return res;
}Typically better than the obvious O(N^2) approach; verify with the template.
- Name what stays true after every move.
- Track the exact condition that lets you discard work safely.
Worked example
Recognition drill
Identify the reusable state and the rule that advances it.
- Restate the goal in one sentence.
- Name the moving parts and what they represent.
- Write the loop invariant before coding.
- Trace one failing case that breaks a naive approach.
Result: You can explain when to reach for the pattern and when to abandon it.
Common pitfalls
- Off-by-one updates on loop bounds.
- Updating state after comparing instead of before.
- Confusing “solved once” with pattern mastery.