AlgoInsight

Free lesson · DSA Mastery - Interview Prep, End to End

Introduction to Sliding Window

Medium6 min readdsasliding-window

Introduction to Sliding Window

Sliding window is one of the highest-leverage techniques in interview prep. It turns a large class of "find the best/longest/shortest contiguous subarray or substring" problems from O(n²) brute force into O(n) single-pass solutions. If prefix sum (Module 11) is about precomputing so range queries are cheap, sliding window is about maintaining a running view of a contiguous range as it slides across the data - adding one element on the right, removing elements on the left, and never re-examining what's already settled.

This introduction lays out the mental model, the two major variants (fixed-size and dynamic-size), the bookkeeping that makes windows work, and exactly when to reach for the technique versus prefix sum, two pointers, or a hash map.

What a Window Actually Is

A "window" is a contiguous range [left, right] over an array or string. As right advances, the element entering on the right is included in the window's running state (a sum, a character-frequency map, a count of distinct values, whatever the problem tracks). When the window needs to shrink, left advances and the departing element is excluded from that same state.

The defining property: each element is added to the window at most once and removed at most once. Both pointers only ever move forward. That's why a sliding window is O(n) even though it has a nested-looking structure - the inner left loop, across the entire run, advances a total of at most n times, not n times per outer step.

graph LR
    subgraph "Window slides right"
    A["left"] -.-> B["[ a b c ]"]
    B -.-> C["right"]
    end
    D["Enter on right:<br/>add to state"] --> E["Exit on left:<br/>remove from state"]

    style A fill:#b45309,stroke:#f59e0b,color:#f1f5f9
    style B fill:#4338ca,stroke:#6366f1,color:#f1f5f9
    style C fill:#b45309,stroke:#f59e0b,color:#f1f5f9
    style D fill:#16a34a,stroke:#10b981,color:#f1f5f9
    style E fill:#dc2626,stroke:#ef4444,color:#f1f5f9
This diagram shows a window as a contiguous range bounded by a left and a right pointer. As the window slides right, the entering element is added to the window's running state, and when the window shrinks from the left, the departing element is removed from that state. Each element enters and leaves at most once.

Interactive animation: Every window of eceba as a grid: the longest-valid window only steps right or down, so it takes 8 steps where a brute force checks 15 windows.

The Two Variants

Almost every sliding-window problem is one of two shapes. Recognizing which you're facing tells you the loop skeleton immediately.

Fixed-Size Windows

Interactive animation: A fixed window of three slides along abciiidef: one letter in, one letter out, and the vowel count is fixed up instead of recounted.

The window has a constant width k given by the problem: "maximum sum of any subarray of length k," "find all anagrams of length m." You advance right, and once the window reaches width k, every further step adds one element on the right and drops one on the left in lockstep. The window size never changes.

The key efficiency: don't recompute the window's state from scratch each step. Maintain it incrementally - add the entering element, subtract the leaving one. That single insight is what separates the O(n) solution from the O(n·k) brute force.

Dynamic-Size Windows

Interactive animation: The shortest window with a sum of at least 7: right grows it, left shrinks it while the sum still holds, ending at length 2.

The window grows and shrinks based on a condition, not a fixed width: "longest substring without repeating characters," "smallest subarray with sum ≥ target," "longest substring with at most k distinct characters." You expand right to include more, and whenever the window violates its condition, you contract left until it's valid again.

Two dynamic shapes recur:

graph TD
    A["Sliding Window"] --> B["Fixed Size k"]
    A --> C["Dynamic Size"]
    B --> D["Add right, drop left<br/>in lockstep"]
    C --> E["Longest valid:<br/>expand, shrink to restore"]
    C --> F["Shortest valid:<br/>expand to satisfy,<br/>shrink while still valid"]

    style A fill:#4338ca,stroke:#6366f1,color:#f1f5f9
    style B fill:#b45309,stroke:#f59e0b,color:#f1f5f9
    style C fill:#b45309,stroke:#f59e0b,color:#f1f5f9
    style D fill:#16a34a,stroke:#10b981,color:#f1f5f9
    style E fill:#16a34a,stroke:#10b981,color:#f1f5f9
    style F fill:#16a34a,stroke:#10b981,color:#f1f5f9
This diagram divides sliding window into two variants. Fixed-size windows add one element on the right and drop one on the left in lockstep, keeping a constant width. Dynamic-size windows either expand and shrink to find the longest valid window, or expand to satisfy a condition then shrink while staying valid to find the shortest.

The Dynamic-Window Skeleton

Nearly every dynamic problem fits one template. Expand the window by moving right; after each expansion, restore validity by moving left; update the answer at the right moment.

int left = 0;
// windowState: a sum, freq map, distinct count, etc.
for (int right = 0; right < n; right++) {
    // 1. include nums[right] in windowState
    while (/* window is invalid */) {
        // 2. exclude nums[left] from windowState
        left++;
    }
    // 3. window [left, right] is now valid -> update answer
}

The three slots - include, restore, update - are where each problem's specific logic lives. The skeleton never changes; what you track in windowState and what "invalid" means is what varies. For shortest-valid problems, the while shrinks while valid and the answer update happens inside the loop instead.

What the Window Tracks (Bookkeeping)

The window's "state" is whatever lets you check the condition in O(1) per step. Common choices:

Choosing the right state is the actual problem-solving step. The window mechanics are identical; the bookkeeping is bespoke.

When to Use Sliding Window

"Contiguous subarray or substring, plus a property that you can update incrementally as the window moves - that's the sliding-window signature."

Reach for it when all of these hold:

A crucial precondition for many window problems: monotonicity. Growing the window must move you monotonically toward (or away from) validity. This is why "subarray sum equals k with negative numbers" is not a sliding-window problem - adding an element can increase or decrease the sum, so shrinking/growing doesn't behave predictably. That problem needs prefix sum + hash map (Module 11). With all-positive values, the sum grows monotonically and a window works.

Interactive animation: Three questions in order: contiguous, predictable as it grows, and is the width given - fixed window, dynamic window, or a different tool.

Sliding Window vs. Neighboring Techniques

Technique Use when Key signal
Sliding window Contiguous range with an incrementally-maintainable property; monotonic behavior "longest/shortest/max contiguous … such that …"
Prefix sum + hash map Subarray sums/counts, possibly with negatives "how many subarrays sum to k" with negatives
Two pointers Sorted array, or pair-from-ends; pointers converge "pair summing to target in sorted array"
Dynamic programming Non-contiguous subsequences, or overlapping subproblems "subsequence," "any order," optimal substructure

Sliding window and two pointers are close cousins - both move forward-only pointers - but a window maintains aggregate state over a range, while classic two pointers compare the two endpoints. Many sources lump them together; the distinction worth keeping is whether you track what's inside the window (window) or just the boundaries (two pointers).

Common Pitfalls Before You Start

Interactive animation: Subarrays that sum to k only suit a window when every number is positive - with negatives, use prefix sum and a hash map.

What This Module Covers

The module is organized by the two variants:

Each problem walks the brute-force → sliding-window arc, so you see why the window is correct, not just that it works. By the end, the dynamic-window skeleton above should be something you can write from memory and adapt on sight.

Let's begin with the fixed-size variant and the cleanest possible example: Maximum Average Subarray I, where the window is a running sum of constant width.

Back to DSA Mastery - Interview Prep, End to End