DAY 5 / 30 · WEEK 1

Sliding Window Pattern

Goal of the day

Concept

Imagine looking at a strip of numbers through a physical window frame that only shows 3 at a time. The brute-force way to find, say, the maximum 3-number sum: slide the frame one step, then re-add all 3 numbers you can see — O(k) work per slide, O(n·k) total. The sliding-window trick: when you slide the frame right by one, you already know the sum inside it — you just subtract the number that left on the left edge and add the number that entered on the right edge. One subtraction, one addition, O(1) per slide, O(n) total. You never recompute from scratch.

That's a fixed-size window. A variable-size window works the same "track what enters and leaves" idea, but the frame itself grows and shrinks: you expand the right edge to bring in new elements, and whenever the window breaks some rule (too big a sum, a repeated character), you shrink from the left edge until it's valid again. Both shapes share the same core move: two pointers marking the window's edges, and O(1) bookkeeping — not a full rescan — every time either edge moves.

Diagrams

1. Fixed-size window (size 3)

[4, 2, 5, 1, 3] — window size k = 3, sliding right by one 4 2 5 1 3 leaves (−4) enters (+1) Old window sum [4,2,5] = 11. New window [2,5,1] = 11 − 4 + 1 = 8 — one subtraction, one addition. No need to re-add 2 and 5, they never left the window.

2. Variable-size window (expand / shrink)

Longest substring without repeats, on "abca" — right hits a repeat a b c a left (index 0) right (index 3) — "a" is already in the window! Window "abc" was valid (length 3, our best so far). Adding this "a" would duplicate it — shrink from the left. Dropping just "a" (index 0) already clears the duplicate. Window becomes "bca" — still length 3.

Interactive visualizations

leaving / duplicate in window, valid entering / right edge outside window

1. Maximum sum subarray of size k

Press Play or Step to begin.

2. Longest substring without repeating characters

Press Play or Step to begin.

The code

// --- Shape 1: fixed-size window ---
function maxSumSubarray(arr, k) {
  let windowSum = 0;
  for (let i = 0; i < k; i++) windowSum += arr[i]; // build the first window once
  let best = windowSum;
  for (let i = k; i < arr.length; i++) {
    windowSum += arr[i] - arr[i - k]; // add entering, subtract leaving
    best = Math.max(best, windowSum);
  }
  return best;
}

// --- Shape 2: variable-size window ---
function lengthOfLongestSubstring(s) {
  const seen = new Set();
  let left = 0, best = 0;
  for (let right = 0; right < s.length; right++) {
    while (seen.has(s[right])) {       // shrink until the duplicate is gone
      seen.delete(s[left]);
      left++;
    }
    seen.add(s[right]);                // now safe to include s[right]
    best = Math.max(best, right - left + 1);
  }
  return best;
}

Line by line:

Dry run: maxSumSubarray([4, 2, 5, 1, 3], k = 3)

iWindowwindowSumbest
[4, 2, 5]11 (initial)11
3[2, 5, 1]11 + 1 − 4 = 811
4[5, 1, 3]8 + 3 − 2 = 911

The best 3-element window is the very first one, [4, 2, 5] = 11 — found in one O(k) setup pass plus two O(1) slides, instead of three separate O(k) resums.

Complexity

ApproachTimeSpaceWhy
Brute force, fixed window (resum every slide)O(n·k)O(1)Every one of ~n windows costs O(k) to sum from scratch.
Sliding window, fixed sizeO(n)O(1)One O(k) setup, then O(1) per slide.
Brute force, all substringsO(n²) or worseO(n)Checking every substring for a property usually costs at least O(n) each.
Sliding window, variable size — numeric constraint (e.g. running sum)O(n)O(1)left/right each move forward at most n times total; no extra structure needed, just a running number.
Sliding window, variable size — set/map-tracked (e.g. no-repeat characters)O(n)O(window size)Same pointer movement, but the window's contents must be tracked in a Set/Map sized to whatever's currently inside it.

Interview corner

How to talk through it out loud: name the window's invariant before coding — "I'll expand right to grow the window, and shrink left with a while loop any time the window has a duplicate, so at every point after the inner loop the window is valid." Stating the invariant is what proves to an interviewer you're not just pattern-matching syntax you memorized.

Practice problems

1. Maximum Average Subarray I (Easy — LeetCode: Maximum Average Subarray I)

Given an array and an integer k, find the contiguous subarray of length k with the maximum average value.

2. Minimum Size Subarray Sum (Medium — LeetCode: Minimum Size Subarray Sum)

Given a target sum and an array of positive integers, find the length of the shortest contiguous subarray whose sum is ≥ target. Return 0 if no such subarray exists.

3. Longest Substring Without Repeating Characters (Medium — LeetCode: Longest Substring Without Repeating Characters)

Given a string, find the length of the longest substring without repeating characters.

Quiz

1. Sliding window applies to problems about:

2. When a fixed-size window slides right by one, what's the O(1) update?

3. In a variable-size window, when do you shrink from the left?

4. Despite having a while loop inside a for loop, why is the variable-window substring pattern O(n) and not O(n²)?

5. Why should you shrink a variable window with a while loop instead of a single if?