Maintain a contiguous window and update its state incrementally: fixed-size averages to variable-size 'longest substring' problems, all in O(n).
0 of 5 lessons checked off
Introduction
What it is
Sliding window maintains a contiguous range [left, right] over a sequence, together with incrementally-updated state (sum, counts, distinct characters) describing what's inside.
Fixed windows slide both edges together (size k given); variable windows expand right greedily and contract left only when a constraint breaks.
Why it matters
Recomputing every subarray from scratch costs O(n·k) or O(n²); updating state by ±1 element makes the whole scan O(n).
'Longest/shortest/count of contiguous ___ satisfying ___' is among the most common interview phrasings, and this is its designated tool.
How it works
Fixed: seed the first window, then add the entering element and remove the leaving one per step.
Variable: for each right, restore validity by advancing left while broken; then record the candidate answer. Both edges only move forward — that one-way motion is the O(n) proof.
State must support O(1) add/remove: sums, hash counts, at-most-k trackers. (Max/min in a window needs a monotonic deque — next topic.)
Where it's used
Rate limiters (requests in the last minute), moving averages in monitoring, network congestion windows, and plagiarism shingling all maintain sliding state.
In interviews
Longest substring without repeating characters, minimum window substring, max sum subarray of size k, longest repeating character replacement, permutation in string, fruit into baskets.
Analogy: A train window moving through a landscape: to know what's visible you don't re-survey the world each second — one scene enters the frame, one leaves, and you adjust your description by exactly those two changes.
Interactive diagram
Add the entering element, subtract the leaving one — two operations replace re-summing the window.
20
11
52
13
34
25
Build the first window of size 3
Sum the first 3 elements once: 8. Re-summing every window from scratch would cost O(n·k); we will slide instead.
sum
8
best
8
1 / 5
Lessons in this topic
Check off lessons as you go — your progress is saved in this browser.
Fixed-size windows
Seed, then add/remove one element per slide.
20 min
Variable-size windows
Expand right, contract left on violation; the while-inside-for shape.
30 min
Window state with hash counts
Distinct characters, at-most-k, and frequency matching.
25 min
Shrinking for minimums
Minimum window substring: contract while VALID instead of while broken.
25 min
When windows don't apply
Negative numbers break sum monotonicity; subsequences aren't contiguous.
15 min
Operations
Fixed-size window
One subtraction and one addition per slide keep the state exact.
20
11
52
13
34
25
Build the first window of size 3
Sum the first 3 elements once: 8. Re-summing every window from scratch would cost O(n·k); we will slide instead.
sum
8
best
8
1 / 5
1defmax_sum_window(nums:list[int],k:int)->int:2"""Maximum sum over all length-k windows. O(n)/O(1)."""3ifk>len(nums):4raiseValueError("window larger than array")5window=sum(nums[:k])6best=window7forrightinrange(k,len(nums)):8window+=nums[right]-nums[right-k]# enter, leave9best=max(best,window)10returnbest
Time: O(n) vs O(n·k) recomputingSpace: O(1)
Edge cases
k equal to len: one window, loop body never runs.
k > len must raise or return a sentinel — decide up front.
Negative values are fine for FIXED windows (state is exact, not monotonic).
Common mistakes
Re-slicing sum(nums[i:i+k]) per position — the O(n·k) this pattern deletes.
Off-by-one on the leaving index (right − k, not right − k + 1... after adding right).
Variable-size window (longest, no repeats)
Expand right each step; while the window is invalid, contract left. Record candidates when valid.
Variable-size window (longest, no repeats)
1deflongest_unique_substring(s:str)->int:2"""Length of longest substring without repeated characters. O(n)."""3last_seen:dict[str,int]={}4left=05best=06forright,chinenumerate(s):7ifchinlast_seenandlast_seen[ch]>=left:8left=last_seen[ch]+1# jump past the duplicate9last_seen[ch]=right10best=max(best,right-left+1)11returnbest
Time: O(n) — left never moves backwardsSpace: O(min(n, alphabet))
Edge cases
The `>= left` guard: stale positions BEFORE the window must not trigger jumps.
Empty string → 0.
left jumps (rather than steps) here because the dict stores exact positions — both forms are O(n).
Common mistakes
left = last_seen[ch] + 1 without the >= left check, dragging left BACKWARDS on stale entries.
Recording best before restoring validity.
Complexity analysis
Operation
Best
Average
Worst
Space
Fixed window scan
O(n)
O(n)
O(n)
O(1)
Variable window (hash state)
O(n)
O(n)
O(n)
O(k) state
Recompute-per-window baseline
O(n·k)
O(n·k)
O(n²)
O(1)
Window max/min (needs monotonic deque)
O(n)
O(n)
O(n)
O(k)
Both pointers move at most n steps forward each — 2n pointer moves total is the entire time proof.
Python implementation
Production-quality code with type hints, validation, and docstrings.
Minimum window substring (the hard-mode template)
1fromcollectionsimportCounter234defmin_window(s:str,t:str)->str:5"""Smallestsubstringofscontainingeverycharoft(withcounts).6O(|s|+|t|)time,O(alphabet)space."""7ifnottornots:8return""9need=Counter(t)10missing=len(t)# chars still required (with multiplicity)11best=(float("inf"),0,0)# (length, left, right)12left=01314forright,chinenumerate(s,1):# right is EXCLUSIVE here15ifneed[ch]>0:16missing-=117need[ch]-=1# surplus chars go negative18
What interviewers expect you to know
Recognition signals
'Longest/shortest/count' + 'substring/subarray/contiguous' + a window-checkable constraint → sliding window.
Size given explicitly ('of size k') → fixed; 'longest such that' → variable expand-contract; 'smallest containing' → contract-while-valid.
Validity know-how
State must update in O(1) per element in AND out — sums, counts, distinct-trackers qualify; medians and maxes need extra machinery.
Positive-only matters for 'sum ≥ target' shrink logic: negatives destroy the monotonicity that justifies contracting (use prefix sums instead).
Subsequence problems are NOT windows — contiguity is the entry ticket.
Follow-ups to expect
"Why is this O(n) when there's a loop in a loop?" — amortised: left only advances, ≤ n total inner steps.
"Window MAXIMUM?" — monotonic deque (next topic) keeps it O(n).
"At most K distinct → exactly K?" — atMost(K) − atMost(K−1), a two-call reduction worth memorising.
Common mistakes
Nested-loop window recompute
Recounting the window's contents per position resurrects the O(n²) you were hired to avoid. State updates by the ONE entering and ONE leaving element.
left moving backwards
Stale hash entries (positions before left) must be ignored — the `>= left` guard. A window whose left retreats voids the O(n) proof AND the answers.
Window on negative-number sum constraints
'Shrink while sum ≥ target' assumes shrinking lowers the sum — false with negatives. Reach for prefix sums + hash map instead.
Answer recorded at the wrong time
Maximums record AFTER restoring validity; minimums record INSIDE the valid-shrink loop. Swapping these produces near-miss wrong answers.
Windowing a subsequence problem
'Longest increasing subsequence' has no contiguity — no window applies. Check the word before the technique.
Practice problems
Hand-picked from the 355-problem DSA Atlas. Reveal hints and solutions progressively; mark and bookmark as you solve.
4 questions across concepts, code output, complexity, and scenarios. Answer all, then submit for explanations.
Frequently asked questions
How is sliding window different from two pointers?
It's the specialisation where both indexes move the same direction and the range BETWEEN them carries maintained state. Converging two-pointers meets in the middle with no window state; the window's essence is incremental bookkeeping.
What state can a window maintain in O(1)?
Sums, counts per value, number of distinct values, matched-character tallies. Order statistics (max/min/median) need auxiliary structures: monotonic deque for max/min, two heaps for median.
Summary & cheat sheet
Key takeaways
Windows solve contiguous problems by ±1-element state updates.
Fixed: slide both edges. Longest: contract while broken. Shortest: contract while valid.