The sliding window pattern
A sliding window maintains a contiguous range over an array or string and updates an aggregate incrementally as the range moves, instead of recomputing it from scratch. That incremental update is what converts an O(n × k) recomputation into O(n).
Fixed windows advance both boundaries in lockstep. Variable windows expand the right edge until a constraint breaks, then contract the left edge until it holds again — which is how "longest substring with…" problems are solved in one pass.
Time and space complexity
| Variant | Time | Space | Typical problem |
|---|---|---|---|
| Fixed-size window | O(n) | O(1) | Max sum of k consecutive elements |
| Variable-size window | O(n) | O(k) | Longest substring without repeats |
| Window with hash map | O(n) | O(k) | Minimum window substring |
| Window with deque | O(n) | O(k) | Sliding window maximum |
| Naive recomputation | O(n × k) | O(1) | The baseline this replaces |
How to use this visualizer
Choose a fixed or variable window problem.
Step through and watch the right edge expand the window.
Watch the left edge contract when the constraint is violated.
Note that the aggregate updates incrementally rather than being recomputed.
Frequently asked questions
A fixed window keeps a constant size: both edges advance together, one element enters and one leaves per step. A variable window changes size to satisfy a constraint — the right edge expands greedily, and the left edge contracts only when the window becomes invalid. Fixed windows suit "every k consecutive elements" questions; variable windows suit longest-or-shortest-satisfying questions.
Because the inner loop does not restart. The left pointer only ever moves forward, and across the entire run it advances at most n times in total. Each element enters the window once and leaves at most once, so the combined work is O(2n) = O(n) despite the nested structure in the code.
Use a sliding window when the answer is about a contiguous subarray or substring and you are tracking an aggregate over that range — a sum, a character count, a distinct-element count. Use two pointers when you are comparing or pairing individual elements, typically converging from both ends of sorted data.