Back to all writing
DSA18 Jun 20263 min readIntermediate

A Sliding Window Checklist You Can Reuse

How to identify fixed and variable windows, maintain the right state, and avoid the off-by-one bugs that make this pattern feel slippery.

sliding-windowstringsarrays

Sliding window problems are usually easier than they first appear. The stress comes from managing state while the interval expands and contracts. Once you decide what the window means, the rest gets much calmer.

Step one: decide whether the window is fixed or variable

Fixed-size window

Use this when the question says things like:

  • subarray of size k
  • substring length exactly k
  • maximum average over k elements

The pattern is:

  1. Build the first window.
  2. Slide one step at a time.
  3. Remove the outgoing element and add the incoming one.

Variable-size window

Use this when the window grows until a condition breaks and then shrinks to restore validity.

This often appears in:

  • longest substring without repeating characters
  • minimum window covering a set
  • smallest subarray with sum at least k

The central question

Ask yourself:

What state lets me tell whether the current window is valid?

Possible answers include:

  • Current sum
  • Frequency map
  • Count of distinct characters
  • Number of satisfied requirements

If your state does not answer validity directly, the implementation gets messy fast.

Template for a variable window

left = 0

for right in range(len(items)):
    add(items[right])

    while window_is_invalid():
        remove(items[left])
        left += 1

    update_answer()

This version works because every element enters the window once and leaves once. That gives linear time.

Example: longest substring without repeating characters

Maintain a frequency map and shrink while any character count exceeds 1.

from collections import defaultdict

def longest_unique(s):
    counts = defaultdict(int)
    left = 0
    best = 0

    for right, ch in enumerate(s):
        counts[ch] += 1

        while counts[ch] > 1:
            counts[s[left]] -= 1
            left += 1

        best = max(best, right - left + 1)

    return best

Common failure modes

Updating the answer in the wrong place

If the answer should only use valid windows, update it after the shrink loop, not before.

Forgetting what left represents

left should mark the start of the current valid window, not the last place you happened to inspect.

Using a map when a scalar would do

If the state is just a running sum, keep it simple. Extra bookkeeping can hide the real idea.

A reusable review pass

Before you submit:

  1. Confirm what makes the window valid.
  2. Confirm which event forces shrinking.
  3. Confirm when the answer is updated.
  4. Confirm the formula for window length: right - left + 1.

That last line sounds basic, but it saves a surprising number of points.

Closing thought

Sliding window is not one trick. It is a small framework for keeping exactly enough state around a moving interval. Once you define the window well, the code becomes much more mechanical.