The Sliding Window Roadmap Nobody Gave You
Every pattern, every trick, and the exact problems to practice — in the order that actually makes it click.

The Sliding Window Roadmap Nobody Gave You
I learned sliding window by solving random LeetCode problems and hoping the pattern eventually “clicks.” But it didn’t, not Fully.
I ended up recognizing the easy ones and freezing on anything slightly different.
Finally I have came up with a diffeerent approach to learn it in a easy way. In this article I have summarised the exact same approach. Instead of throwing a pile of problems at you, we’ll build the concept from the ground up — what a window actually is, how to tell when a problem needs one, and then walk through two problems in full detail so the logic actually sticks. At the end, you get a practice list in the right order.
If you’ve ever solved a sliding window problem by copying a pattern you memorized without really knowing why it worked — this is for you.
What is a sliding window, really?
A sliding window is just a range(continious numbers) inside an array or string that you track using two pointers — usually called left and right. Instead of looking at every possible sub-range separately (which is slow), you move these two pointers forward and adjust your answer as you go.
Ex - [2,4,3,1,5] k =3
Find largest number in window of k size
APPROACH-I
Brute Force: Repeatably checking a sub range of size k
for(i =0 to i =n-k){
let max = -Infinity;
for(j=i to j<i+3){
max = Math.max(max, arr[j])
}
ans.push(max)
}
return max
APPROACH- 2
Sliding Window:
1. Make a window of 3, once window become k size, shrink it by moving left
[2,4,3]
| |
l r
max = 4
2.After moving left [4,3] , window size decreased move r
[4,3,1]
| |
l r
max = 4
3. Again move left [3,1], window size decreased move r
[3,1, 5]
| |
l r
max = 5
//We'll see complete code in detail this is just to make you understand sliding window functioningThe core idea: don’t recalculate everything from scratch every time. When you move the window forward, only account for what left and what entered.
That’s the entire concept. Everything else is just applying it to different situations.
How to recognize a sliding window problem
Before touching code, check the question for these signs:
It mentions “contiguous subarray” or “substring”
It’s asking for the longest, shortest, or a fixed-size chunk that satisfies some condition
You need a running sum, count, or set of unique elements over a moving range
The brute-force solution would check every possible sub-range, giving you O(n²) or worse
If two or more of these apply, sliding window is very likely the way to go.
There are two flavors of this pattern, and it’s important to know which one you’re dealing with before you start coding:
Fixed window — the size never changes (e.g., “sum of exactly k elements”)
Variable window — the size grows and shrinks based on a condition (e.g., “longest substring without repeats”)
Let’s do one of each.
Problem 1: Maximum Sum Subarray of Size K (fixed window)
The question: Given an array of numbers and a number k, find the maximum sum of any k consecutive elements.
Brute force first, because seeing why it’s slow makes the optimization obvious:
function maxSumBruteForce(arr, k) {
let maxSum = -Infinity;
for (let i = 0; i <= arr.length - k; i++) {
let currentSum = 0;
for (let j = i; j < i + k; j++) {
currentSum += arr[j]; // recalculating the whole window every time
}
maxSum = Math.max(maxSum, currentSum);
}
return maxSum;
}The problem: every time the window shifts by one position, you’re re-adding almost the same numbers you already added in the previous step. That’s wasted work. Time complexity is O(n*k).
Sliding window version:
function maxSumSlidingWindow(arr, k) {
let windowSum = 0;
// build the first window
for (let i = 0; i < k; i++) {
windowSum += arr[i];
}
let maxSum = windowSum;
// slide the window one step at a time
for (let i = k; i < arr.length; i++) {
windowSum += arr[i]; // add the element entering the window
windowSum -= arr[i - k]; // remove the element leaving the window
maxSum = Math.max(maxSum, windowSum);
}
return maxSum;
}Instead of recalculating the full sum each time, you add the new element and subtract the one that fell out of range. That’s it. This brings the time complexity down to O(n).
Notice the pattern: build the first window, then slide it. You’ll see this exact structure in almost every fixed-window problem.
Problem 2: Longest Substring Without Repeating Characters (variable window)
The question: Given a string, find the length of the longest substring with no repeating characters.
Example: for "abcabcbb", the answer is 3 ("abc").
This is where a lot of people get stuck — not on expanding the window, but on knowing exactly how much to shrink it when a repeat shows up.
function longestUniqueSubstring(s) {
let seen = new Map(); // character -> last seen index
let left = 0; // left edge of the window
let maxLength = 0;
for (let right = 0; right < s.length; right++) {
const char = s[right];
// if this character was seen before, and it's inside the current window
if (seen.has(char) && seen.get(char) >= left) {
// move left to just after the previous occurrence
left = seen.get(char) + 1;
}
seen.set(char, right);
maxLength = Math.max(maxLength, right - left + 1);
}
return maxLength;
}Here’s what’s happening step by step: you expand right and record each character's position. If you hit a character that's already inside your current window, you don't restart from zero — you move left to just after where that character last appeared. The window shrinks by exactly the right amount, nothing more.
This is the part most explanations skip. A simpler (but slightly less efficient) way to handle the shrinking is a while loop that moves left forward one step at a time until the duplicate is gone. That version is easier to reason about when you're starting out — use it first, then switch to the jump-based version once it makes sense.
Compare the two problems: same two-pointer skeleton, but problem 1 keeps the window size fixed, while problem 2 lets it grow and shrink based on a condition. That’s the entire difference between fixed and variable window problems.
Fixed vs Variable — quick reference

Image- Fixed vs Variable — quick reference
Common mistakes to watch for
Unclear window boundaries. Decide early whether your window is
[left, right]inclusive or[left, right)exclusive, and stay consistent across every problem you solve.Not shrinking the window when the condition breaks. This is the most common bug in variable-window problems. Shrink from the left before expanding further.
Using the wrong data structure to track the window’s contents. A
Setonly tells you if something exists. AMapgives you position or frequency. Problems like Minimum Window Substring need frequency counts, so aSetwon't be enough.
Practice roadmap: what to solve, in order
Solving these in sequence builds the pattern properly instead of leaving gaps:
Foundation (fixed window):
Maximum Sum Subarray of Size K
Average of Subarrays of Size K
Getting comfortable with variable window:
Longest Substring Without Repeating Characters
Longest Subarray with Sum ≤ K
Fruit Into Baskets
Where it gets harder:
Minimum Size Subarray Sum
Longest Repeating Character Replacement
Permutation in String
Advanced:
Minimum Window Substring
Sliding Window Maximum (this one uses a deque instead of a simple pointer — different enough that it deserves its own separate explanation)
Solve them roughly in this order. The earlier problems are training you for the shrink/grow logic the harder ones require.
Wrapping up
The core idea behind sliding window is simple: avoid redoing work you’ve already done. Every problem in this pattern comes down to tracking a left and right pointer and updating your answer incrementally instead of recalculating from scratch.
Once you see it this way, the pattern stops feeling like a memorized trick and starts feeling like common sense.
What sliding window problem gave you the most trouble the first time you saw it? Curious if it’s the same one that gave others trouble too.