Lesson 5 of 30
Sliding Window
Avoid recomputing overlapping work by growing and shrinking a window over an array or string in one pass — fixed-size sums, longest-substring problems, and a real debounce framing.
Sliding window is two pointers' close cousin, specialized for a specific shape of problem: "look at every contiguous run of size k" or "find the longest/shortest contiguous run satisfying some condition." The naive approach recomputes each run from scratch. The sliding window approach notices that consecutive runs overlap almost entirely, and updates incrementally instead of recomputing.
Fixed-size window: maximum sum of k consecutive elements
function maxSumOfSizeK(arr, k) {
let windowSum = 0;
for (let i = 0; i < k; i++) windowSum += arr[i]; // first window, computed once
let maxSum = windowSum;
for (let end = k; end < arr.length; end++) {
windowSum += arr[end] - arr[end - k]; // add the new element, remove the one that fell out
maxSum = Math.max(maxSum, windowSum);
}
return maxSum;
}The naive version would sum k elements at every one of roughly n
positions — O(n * k). This version computes the first window's sum once,
then updates it in O(1) per step by adding exactly one new element and
subtracting exactly one departing element. Total: O(n) time, O(1) auxiliary
space. This is the same "maintain a running total instead of recomputing"
idea behind the prefix-sum technique two lessons from now, applied to a
moving range instead of a fixed one from the start.
Variable-size window: longest substring without repeating characters
Fixed windows have a known size. Variable windows grow and shrink based on a condition — and this is where sliding window earns its reputation as the pattern behind a large share of real string problems:
function longestUniqueSubstring(str) {
const seen = new Set();
let left = 0;
let longest = 0;
for (let right = 0; right < str.length; right++) {
while (seen.has(str[right])) {
seen.delete(str[left]);
left++;
}
seen.add(str[right]);
longest = Math.max(longest, right - left + 1);
}
return longest;
}Walk through the logic: right extends the window by one character every
step. If that character is already in the window (seen.has(...)), the
window can't grow past it while staying duplicate-free — so left advances,
removing characters from the window, until the duplicate is gone. Only
then does the new character get added and the window's length gets checked
against the best seen so far.
The subtlety that makes this O(n) rather than O(n²): although there's a
while loop nested inside a for loop, left only ever moves forward and
never resets. Across the entire run of the algorithm, left makes at most
n total moves and right makes exactly n moves — 2n total pointer
steps, not n * n. This is the same monotonic-pointer argument from the
two-pointers lesson, applied to a window instead of two independent ends.
- Step 1
right at 'a', 'b', 'c'
Window = "abc", no duplicates yet, longest = 3.
- Step 2
right at second 'a'
'a' is already in the window. left advances past it, removing 'a' from the set.
- Step 3
Window becomes "bca"
No duplicates now — add the new 'a', longest stays 3.
- Step 4
Continue to the end
The same shrink-then-grow logic repeats; longest never exceeds 3 for this input.
A real frontend framing: a live-typing character limit
Sliding window isn't just for interview strings. A "no more than N unique tags in the visible filter chips" feature, or a live text area that highlights the longest run of non-repeating characters as a typing-quality indicator, is literally this algorithm running on real user input, not a contrived example.
What to remember
- Fixed-size sliding window avoids recomputing overlapping sums by updating a running total: add what entered, subtract what left. O(n * k) becomes O(n).
- Variable-size sliding window grows the right edge greedily and only shrinks the left edge when a condition (like "no duplicates") would otherwise be violated.
- The reason a nested-looking window is still O(n) overall: both pointers are monotonic — each only moves forward, for a bounded total of roughly 2n moves across the whole run, not n².
- This pattern is the conceptual backbone of debouncing (covered later in this course) — a window that keeps extending while events arrive and resolves once they stop.
Check yourself
4 questions · pass 3/4 to unlock In-Place Array Manipulation
1.A naive solution to "find the maximum sum of any 5 consecutive elements" recomputes the sum of all 5 elements at every starting position. What is its time complexity, and why does the fixed-size sliding window beat it?
2.In the variable-size "longest substring without repeating characters" pattern, what causes the left edge of the window to move forward?
3.Why is the variable-size sliding window over a string of length n still considered O(n) overall, even though there's a loop for the right edge and a loop (or while) for the left edge?
4.A search-as-you-type feature buffers keystrokes and only fires a request once no new keystroke has arrived for 300ms. Which sliding-window idea does this most resemble?
4 left to answer