2Brute2Best
🔥0

Sliding Window Maximum

Hard·LeetCode #239Basic Anchor
LeetCode
30-Second Mental ModelFixed Sliding Window + Monotonic Decreasing Deque
Complexity:O(N · K)→O(N)
Key Insight

Keep a deque of indices whose values go down from front to back. When a new element arrives, throw away every element at the back that is ≤ it — they can never be the max again. Drop the front when it slides out of the window. The front is always the window max.

Core Validity Invariant

An element is worth keeping only if no element after it in the window is bigger or equal. The window itself is always valid when it has exactly k elements — the deque just answers "what is the max?" in O(1).

01

Problem

You are given an integer array nums and a number k.

A window of size k starts at the left end of the array and moves one step to the right at a time, until it reaches the right end. At every position, the window covers exactly k neighbouring elements.

Return a list with the largest value inside the window at each position, from left to right.

Input

An integer array nums of length n, and an integer k.

Output

An array of n − k + 1 numbers: the maximum of each window of size k, in order.

Example 1
Input: nums = [1, 3, -1, -3, 5, 3, 6, 7], k = 3
Output: [3, 3, 5, 5, 6, 7]

The windows are [1,3,-1], [3,-1,-3], [-1,-3,5], [-3,5,3], [5,3,6], [3,6,7]. Their maxima are 3, 3, 5, 5, 6, 7.

Example 2
Input: nums = [1], k = 1
Output: [1]

There is only one window and it holds just 1.

Example 3
Input: nums = [9, 10, 9, -7, -4, -8, 2, -6], k = 5
Output: [10, 10, 9, 2]

When the 10 slides out, the next biggest value 9 takes over. When that 9 slides out too, the max drops all the way to 2.

Constraints
  • • 1 ≤ n ≤ 10^5
  • • −10^4 ≤ nums[i] ≤ 10^4
  • • 1 ≤ k ≤ n
02

First, think yourself

Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.

  1. 1.

    Is the window size fixed or does it change?

  2. 2.

    When the window moves one step, which element enters and which one leaves?

  3. 3.

    If I know the max of the current window and the max element leaves, do I know the new max?

  4. 4.

    If a big number arrives, is there any reason to keep remembering the smaller numbers that came before it?

  5. 5.

    What would I need to store so that the "next max" is ready the moment the current max leaves?

03

Brute force approach

04

Better approach

05

Optimized approach

06

Why does this algorithm work?

07

Dry run

08

All approaches compared

ApproachIdeaTimeSpace
Brute ForceFor each of the n − k + 1 windows, scan its k elements for the maxO(N · K)O(1)
BetterKeep the window's values in a multiset; the largest is at the endO(N log K)O(K)
OptimalKeep only indices that can still become the max, values decreasing front to backO(N)O(K)
09

Why does this belong to this pattern?

Clues in the problem statement
  • “window of size k moves one step at a time”Fixed sliding window — one element enters and one leaves at every step.
  • “largest value inside the window”The aggregate is a max, which cannot be fixed in O(1) when an element leaves → need a structure that keeps backup candidates.
  • “at every position”We need the max many times as the window moves, so it must be cheap to read each time.
Contiguous range+fixed size k+max of the window at every step→Fixed Sliding Window + Monotonic Decreasing Deque

This is the anchor problem for the deque sub-pattern. The window part is easy (fixed size). The new idea is the deque that throws away elements that can never be the max again. The next questions in this sub-pattern reuse the same deque, but inside a variable window, where the max (and min) decide whether the window is valid.

10

Don't make this mistake

Storing values instead of indices
✗ dq.push_back(nums[right]);
✓ dq.push_back(right);

With only values, you can't tell when the front has slid out of the window. Store indices and read the value with nums[i].

Popping the front by value instead of by position
✗ if (nums[dq.front()] == nums[right - k]) dq.pop_front();
✓ if (dq.front() <= right - k) dq.pop_front();

Comparing values breaks when values repeat. Compare the index with the window's left edge.

Erasing a value from a multiset with erase(value)
✗ window.erase(nums[right - k]);
✓ window.erase(window.find(nums[right - k]));

erase(value) removes every copy of that value. You only want to remove the one copy that left the window.

Thinking you need a sum-style O(1) update

Pattern confusion: in Max Sum Subarray of Size K you can keep one running sum. A max does not work that way — if the max leaves, a single variable can't tell you the next one. Whenever the window aggregate is a max or min, reach for the monotonic deque, not a single variable.

Assuming the inner while loop makes it O(N · K)

Count pops, not loops. Each index is pushed once and popped at most once over the whole run, so the total number of pops is at most n.

11

Want to implement this?

Write it yourself on LeetCode, then come back and compare your code with the solutions above.

Open coding workspace
How did it go?
Beyond The LeetCode Problem

How this concept connects to System Design & C++ Systems

Bridge DSA with production engineering

Top engineering interviews test whether you understand how algorithms like Sliding Window translate into production architectures and low-level memory mechanics.