Module 5: Stacks, Queues & Monotonic Structures·Tutorial 9 of 23 (Step 5.2)
All Tutorials·DSA Roadmap·3 Problems · ~8 hrs

5.2 Monotonic Stack & Monotonic Deque

Understand what 'Monotonic' means, why keeping a stack sorted turns O(N^2) 'next greater' searches into O(N), and how a Monotonic Deque tracks window maximums.

01 Read the story: What & Why
02 Follow the drawing: Visual stepper
03 Practice code: 4 languages + problems

1. What Is a Monotonic Stack / Deque?

The word "monotonic" simply means "always staying in sorted order" (either strictly increasing or strictly decreasing from bottom to top).

A Monotonic Stack is a normal Stack with one extra rule before you push(x):

  • Monotonic Decreasing Stack: Before pushing x, pop every item on top of the stack that is smaller than x.
  • Monotonic Increasing Stack: Before pushing x, pop every item on top of the stack that is larger than x.
Visual: Monotonic Decreasing Stack — Incoming 75 Pops Shorter Bars (71, 69)
Stack Before: [78, 71, 69]New 75 arrives ──► Pops 69 & 71!Stack After: [78, 75]75 is the "Next Greater Element" for both 69 and 71. Each item is pushed & popped once → O(N)!

2. Why Do We Need It & How Does It Turn O(N^2) into O(N)?

The Pain Without a Monotonic Stack (O(N^2))

Suppose you are given daily temperatures [73, 74, 75, 71, 69, 72, 76] and asked: "For each day, find the first future day that is warmer (Next Greater Element)." Scanning to the right from every single day takes O(N^2).

The Breakthrough Intuition

Hold indices of "days still waiting for a warmer day" on a Monotonic Decreasing Stack:

  • Day 0 (73) waits on the stack: [0 (73)].
  • Day 1 (74) arrives! Since 74 > 73, Day 0's wait is over! Pop Day 0, record its answer (1 - 0 = 1 day), and push Day 1.
  • Day 3 (71) and Day 4 (69) are cooler than 75, so they pile up on the stack: [2 (75), 3 (71), 4 (69)] (notice they are in decreasing order!).
  • When Day 5 (72) arrives, it immediately pops both 69 and 71!

Why is this O(N)? Because even though there is a while loop inside a for loop, each element is pushed onto the stack once and popped at most once across the entire run (2N operations total)!

Cheat Sheet: Which Monotonic Stack Flavor Should You Use?

Goal in the ProblemStack Order (Bottom → Top)Pop Condition (while stack and ...)Classic Example
Next Greater Element (to the right)Monotonic Decreasingnums[stack[-1]] < currDaily Temperatures, Next Greater Element I
Next Smaller Element (to the right)Monotonic Increasingnums[stack[-1]] > currLargest Rectangle in Histogram, Final Prices With Discount
Sliding Window Maximum (size K)Monotonic Decreasing Dequenums[dq[-1]] <= curr (plus evict dq[0] <= i - k)Sliding Window Maximum
The Hand-Drawn Step-by-Step Walkthrough
Step 1 / 2

Interactive Step-by-Step Trace: Monotonic Stack for Next Greater Element

Trace temperatures = [73, 74, 75, 71, 69, 72, 76]:

Step 1: 71 and 69 are cooler than 75 — Keep Waiting on Stack
waiting75 (idx 2)
waiting71 (idx 3)
TOP69 (idx 4)Smallest
Stack holds decreasing temperatures: [75, 71, 69]

Because 75 > 71 > 69, none of them have seen a warmer day yet. They wait in decreasing order.

✎ Remember this: A monotonic decreasing stack keeps the smallest waiting element on TOP.

3. Basic Operations & Walkthroughs (All 4 Languages)

from collections import deque

# 1. Monotonic Decreasing Stack: Next Greater Element / Daily Temperatures -> O(N)
def daily_temperatures(temperatures: list[int]) -> list[int]:
  ans = [0] * len(temperatures)
  stack = []  # stores indices waiting for a warmer day
  for i, temp in enumerate(temperatures):
      while stack and temperatures[stack[-1]] < temp:
          prev_idx = stack.pop()
          ans[prev_idx] = i - prev_idx
      stack.append(i)
  return ans

# 2. Monotonic Decreasing Deque: Sliding Window Maximum -> O(N)
def max_sliding_window(nums: list[int], k: int) -> list[int]:
  dq = deque()  # stores indices in decreasing order of values
  res = []
  for i, x in enumerate(nums):
      while dq and nums[dq[-1]] <= x:
          dq.pop()        # smaller old values can never be window max
      dq.append(i)
      if dq[0] <= i - k:
          dq.popleft()    # evict index that fell out of the left side
      if i >= k - 1:
          res.append(nums[dq[0]])
  return res

4. Core Interview Patterns & Common Traps

Pattern: Monotonic Stack (Next Greater Element) & Monotonic Deque (Window Max)

Use a Monotonic Stack when looking for the nearest greater/smaller element to the left or right; use a Monotonic Deque when you also need to evict elements falling out of a sliding window.

# Monotonic Decreasing Stack (Next Greater Element to the Right):
stack = []  # stores indices
for i, x in enumerate(nums):
  while stack and nums[stack[-1]] < x:
      idx = stack.pop()
      next_greater[idx] = x
  stack.append(i)
Operation / PatternTimeSpaceNotes
Next Greater / Smaller ElementO(N)O(N)Monotonic Stack; each index pushed & popped once
Largest Rectangle in HistogramO(N)O(N)Monotonic Increasing Stack finds first smaller bar on left & right
Sliding Window Maximum (Deque)O(N)O(K)Front of deque always holds current window max in O(1)

5. Practice On Your Own (Curated Submodule Problems)

0 / 3 Solved
StatusProblemDifficultyComplexityHint?Links & Notes
Daily Temperatures
Monotonic Increasing / Decreasing Stack
Medium
T: O(N)
S: O(N)
Solve
Largest Rectangle in Histogram
Monotonic Increasing / Decreasing Stack
Hard
T: O(N)
S: O(N)
Solve
Sliding Window Maximum
Monotonic Deque (Sliding Window Max)
Hard
T: O(N)
S: O(K)
Solve