Lesson 093 min read

Monotonic Stack

November 05, 2026

// TL;DR

A monotonic stack keeps its elements in order (increasing or decreasing). You push while the order holds; when a new element would break it, you POP the out-of-order ones — and each pop is where you 'answer' that popped element (its next-greater or next-smaller). Because every element is pushed once and popped at most once, the total work is O(n) even though it looks nested. Signals: 'next greater/smaller element', 'how many days until…', 'largest rectangle in histogram', 'trapping rain water', 'stock span'. The stack usually holds INDICES (so you can compute distances). Decreasing stack → next greater; increasing stack → next smaller.

The monotonic stack is the pattern people find magical: a plain stack, kept in sorted order, that answers “what’s the next bigger thing?” for every element in O(n) total. It feels like it should be O(n²), and the reason it isn’t is the heart of the trick.

The idea

Monotonic stack, the next greater element. On temperatures 73, 74, 75, 71, 69, 72 the answer, days until a warmer temperature, is 1, 1, 3, 2, 1, 0. How the stack moves: push indices while temps keep rising; when a higher temp arrives, pop every smaller one and record the distance; the stack stays monotonic, decreasing. Why it's O(n) not O(n squared): each index is pushed once and popped at most once, so total work is linear even though it looks nested; the stack remembers who is still waiting for an answer. The idea: a monotonic stack keeps its elements in order; you push as long as the order holds, and when a new element would break it you pop the out-of-order ones, and each pop is where you answer that element. Use it for next greater or smaller element, daily temperatures, largest rectangle in histogram, stock span, trapping rain water.

Keep a stack whose values are always in order (say, decreasing). Walk the array:

  • While the stack’s top is smaller than the current element, pop it — and the current element is that popped element’s “next greater”. Record the answer at the moment of popping.
  • Then push the current element (its index).

Each element is pushed once and popped at most once, so the total number of operations is O(n) — even though the inner “while pop” loop makes it look quadratic. The stack is acting as a memory of “elements still waiting for their next-greater.”

The template: daily temperatures

“For each day, how many days until a warmer temperature?” — store indices so you can compute the distance:

def daily_temperatures(T):
    res = [0] * len(T)
    stack = []                         # indices, temps decreasing
    for i, t in enumerate(T):
        while stack and T[stack[-1]] < t:
            j = stack.pop()            # day j finally gets a warmer day
            res[j] = i - j             # distance
        stack.append(i)
    return res
# daily_temperatures([73,74,75,71,69,72,76,73]) -> [1,1,4,2,1,1,0,0]

Decreasing stack → next greater. Flip the comparison for an increasing stack → next smaller.

Worked example: largest rectangle in histogram

The famous hard one. For each bar, you want the widest rectangle it can anchor — bounded by the first smaller bar on each side. A monotonic (increasing) stack finds those boundaries in O(n):

def largest_rectangle(heights):
    stack = []; best = 0
    heights = heights + [0]            # sentinel flushes the stack at the end
    for i, h in enumerate(heights):
        while stack and heights[stack[-1]] >= h:
            height = heights[stack.pop()]
            width = i - stack[-1] - 1 if stack else i   # span to the left boundary
            best = max(best, height * width)
        stack.append(i)
    return best
# largest_rectangle([2,1,5,6,2,3]) -> 10   (5 and 6 → 2 wide × 5 high)

The same machinery (find the span bounded by smaller elements on both sides) solves trapping rain water and maximal rectangle in a binary matrix.

Step-by-step walkthrough

Trace Daily Temperatures on [73, 74, 75, 71, 69, 72, 76, 73]. The stack holds indices of days still waiting for a warmer day, in decreasing temperature order. Each new day pops every colder day it beats — and those days get their answer.

day temp popped (day(temp)→wait) stack after
0 73 — [0(73)]
1 74 0(73)→1d [1(74)]
2 75 1(74)→1d [2(75)]
3 71 — [2(75), 3(71)]
4 69 — [2(75), 3(71), 4(69)]
5 72 4(69)→1d, 3(71)→2d [2(75), 5(72)]
6 76 5(72)→1d, 2(75)→4d [6(76)]
7 73 — [6(76), 7(73)]

Every index is pushed once and popped at most once, so it’s O(n). Final answer: [1, 1, 4, 2, 1, 1, 0, 0].

When to reach for it

Signals: “next greater / next smaller element”, “how many steps until a bigger value” (daily temperatures, stock span), histogram / rectangle area, trapping rain water. Whenever you need, for each element, the nearest bigger-or-smaller neighbour, reach for a monotonic stack.

Pitfalls

  • Storing values instead of indices. Most of these problems need distances or widths, so store indices and look up values as needed.
  • Wrong monotonic direction / comparison. Decreasing stack gives next-greater; increasing gives next-smaller. Pick based on what you’re answering, and be careful with > vs >= (ties).
  • Forgetting the sentinel. A trailing 0 (or iterating one past the end) flushes any elements still on the stack at the end — otherwise their answers are never recorded.

Recap

A monotonic stack keeps elements in sorted order; when a new element breaks the order you pop and answer each out-of-order element (its next greater/smaller). Each element enters and leaves once → O(n). Store indices; decreasing stack = next-greater, increasing = next-smaller. Signal: next greater/smaller, days-until, histogram, rain water.

Practice: 11 solved problems on monotonic stack → — cover each one, solve it yourself, then check the tested code.

Next: Lesson 10 — Binary Search, halving the search space.

exercisePractice this patternMonotonic Stack — Practice Problemsarrow_forward