Coding interview prep

July 4, 2026

Monotonic Stack: The Pattern Behind Next Greater Element and Daily Temperatures

A monotonic stack is the trick that turns a whole family of O(n²) array problems into a single O(n) pass. The idea is small, but it is genuinely hard to picture from code alone, because the whole algorithm is about what happens on a stack you cannot see. So we are going to watch it run.

Most people meet the monotonic stack as a magic trick. You read the next-greater-element solution, it is only eight lines, every line makes sense, and yet you could not have written it and you cannot reproduce it a week later. The reason is that the code describes the mechanics but hides the intuition. Nothing on the page tells you why the elements you pop are exactly the ones that were waiting for an answer.

The honest way to learn it is to stop reading the final code and instead watch the stack fill and drain as you scan the array. Once you see that each element is pushed once, waits on the stack until a bigger value arrives, and is popped exactly when its answer appears, the pattern stops being a trick and becomes obvious.

The trigger: 'next greater' and 'next smaller' problems

A monotonic stack is the answer to a very specific question shape: for each element, find the next (or previous) element that is greater than it, or smaller than it. The canonical version is Next Greater Element — given an array, for every position return the first value to its right that is larger, or -1 if there is none.

The brute force is obvious and quadratic: for every element, walk right until you find something bigger. That is O(n²), and for a sorted-descending array it does the full n² work. The monotonic stack does the same job in O(n) by keeping a stack of elements that are still waiting for their next greater value, and resolving them the instant that value shows up.

How to spot it in an interview

The words to listen for are "next greater", "next smaller", "previous greater", "warmer", "taller", "how many days/steps until", and "nearest larger to the left/right". If a problem asks you to relate each element to the closest bigger or smaller element in some direction, a monotonic stack is almost always the O(n) tool. Histogram and skyline problems are the same pattern in disguise.

Watch the stack push, wait, and pop as it resolves the next greater element for [2, 1, 2, 4, 3]:

Next greater element for [2, 1, 2, 4, 3]

SCAN

Array (index scanning left to right)

2
1
2
4
3

Stack (indices, values decreasing ↓)

empty

Step 1/14: Scan index 0 (value 2). Does it resolve anything waiting on the stack?

Next greater element (result)

-1
-1
-1
-1
-1

Every index is PUSHED once and waits on the stack. When a larger value arrives, it POPS every smaller index that was waiting and records that larger value as their answer. Watch step 6: the 4 arrives and pops both the 2 and the 2 before it, resolving two answers in one move. That is why the total work is linear — each index is pushed once and popped at most once.

Why it is O(n): the pushed-once, popped-once argument

The inner while loop that pops the stack looks like it could make the whole thing quadratic — a loop inside a loop. It does not, and the reason is the heart of the pattern. Across the entire scan, every index is pushed onto the stack exactly once, and once it is popped it never returns. So the total number of pops over the whole run is at most n, no matter how the array is shaped.

That is the amortized argument interviewers want to hear: the inner loop can pop several elements on one step, but those pops are "paid for" by the single push that put each element there. n pushes and at most n pops means O(n) total, even though a single step can do a lot of work.

This is also the sentence that separates a strong candidate from a memorizer. A memorizer says "it is a stack that stays sorted". A strong candidate says "the stack holds indices still waiting for their next greater element; a new value pops exactly the ones it resolves; each index is pushed and popped once, so it is linear". Same code, completely different level of understanding.

The universal template

Almost every monotonic stack solution is this exact shape. What changes between problems is tiny: the comparison direction (greater vs smaller), whether you store indices or values, and what you record when you pop. The scan-and-pop skeleton never changes.

0

The monotonic stack skeleton (Next Greater Element)

Scan once, pop everything the current value resolves, then push

function nextGreater(nums) {
  const res = new Array(nums.length).fill(-1);
  const stack = [];              // holds INDICES, values kept decreasing

  for (let i = 0; i < nums.length; i++) {
    // current value resolves every smaller index waiting on top
    while (stack.length &&
           nums[i] > nums[stack[stack.length - 1]]) {
      const t = stack.pop();     // t was waiting; its answer is nums[i]
      res[t] = nums[i];
    }
    stack.push(i);               // i now waits for ITS next greater
  }
  return res;                    // whatever stays unresolved keeps -1
}

What makes it work

stack holds INDICES, not values — the index gives you distance for free

while nums[i] > nums[top] — a decreasing stack finds next GREATER

each index pushed once, popped at most once → O(n) total

Use when

Any problem that asks for the next or previous greater/smaller element, or a distance to it. Store indices when you need the position or the gap (days, width); store values when you only need the value.

Classic problems

LC 496 · Next Greater Element ILC 503 · Next Greater Element IILC 739 · Daily TemperaturesLC 84 · Largest Rectangle in Histogram

Store indices, not values

Beginners store values on the stack; experienced solvers store indices. The index gives you the value for free (nums[i]) and, crucially, the distance. In Daily Temperatures the answer is "how many days until warmer", which is just i - t. You cannot compute that gap if the stack only remembers values. When in doubt, push indices.

Increasing vs decreasing: which stack do you need?

This is the one decision that trips everyone up, and it flips based on a single word in the problem. The direction of the stack is opposite to the direction of what you are looking for, which feels backwards until you say it out loud a few times.

Decreasing stack

Pop while the current value is greater than the top. Values on the stack stay in decreasing order.

Finds the next GREATER element.

Increasing stack

Pop while the current value is smaller than the top. Values on the stack stay in increasing order.

Finds the next SMALLER element.

The mnemonic that sticks: you pop when you have found the answer. If you want the next greater element, the answer arrives when a bigger value shows up, so you pop on "greater", which leaves a decreasing stack behind. Flip the comparison to < and the exact same skeleton finds next-smaller instead. Previous-greater / previous-smaller is the same again, just read the stack top before you push instead of popping.

Pattern in the wild: Daily Temperatures (LC 739)

Daily Temperatures is the same algorithm with one change: instead of recording the next greater value, you record the distance to it. Given daily temperatures, for each day output how many days you wait for a warmer one. Because the stack holds indices, the gap is just i - t.

1

Daily Temperatures

Next greater, but the answer is the distance, not the value

function dailyTemperatures(temps) {
  const res = new Array(temps.length).fill(0);
  const stack = [];              // indices of days awaiting a warmer day

  for (let i = 0; i < temps.length; i++) {
    while (stack.length &&
           temps[i] > temps[stack[stack.length - 1]]) {
      const t = stack.pop();
      res[t] = i - t;            // days until warmer = the index gap
    }
    stack.push(i);
  }
  return res;
}

What makes it work

res[t] = i - t — the index gap IS the answer (why we store indices)

same decreasing stack as next-greater — only the recorded value changed

days that never warm up keep 0, the initial fill value

Use when

The problem asks how far until the next larger/smaller value: days until warmer, distance to the next taller building, span since the last higher price.

Classic problems

LC 739 · Daily TemperaturesLC 901 · Online Stock SpanLC 1019 · Next Greater Node In Linked List

Pattern in the wild: Largest Rectangle in Histogram (LC 84)

This is the problem that makes the monotonic stack feel like a superpower. For each bar, the widest rectangle it can anchor extends until it hits a shorter bar on either side. An increasing stack finds exactly those boundaries: when a bar is shorter than the stack top, that top's rectangle is now closed, and the width is the gap between the new boundary and the element below it on the stack.

2

Largest Rectangle in Histogram

An increasing stack, popped when a shorter bar closes a rectangle

function largestRectangle(heights) {
  const stack = [];              // indices, heights increasing
  let best = 0;

  for (let i = 0; i <= heights.length; i++) {
    const h = i === heights.length ? 0 : heights[i];
    // a shorter bar closes every taller rectangle on the stack
    while (stack.length && h < heights[stack[stack.length - 1]]) {
      const top = stack.pop();
      const height = heights[top];
      const width = stack.length ? i - stack[stack.length - 1] - 1 : i;
      best = Math.max(best, height * width);
    }
    stack.push(i);
  }
  return best;
}

What makes it work

increasing stack → pop on SMALLER (h < top) to find both boundaries

width = i - stack[top-1] - 1 — the left boundary is the new stack top

the final h = 0 sentinel flushes every remaining bar

Use when

Rectangles, spans, or areas bounded by the nearest smaller element on each side. The same idea powers Maximal Rectangle (LC 85) and Trapping Rain Water (LC 42).

Classic problems

LC 84 · Largest Rectangle in HistogramLC 85 · Maximal RectangleLC 42 · Trapping Rain Water

The sentinel trick

Notice the loop runs to i <= heights.length and treats the extra step as height 0. That imaginary zero-height bar at the end is shorter than everything, so it forces the stack to flush and close every rectangle still open. Sentinels like this — a 0 at the end, or an infinity at the start — are a common monotonic stack move to avoid a separate cleanup loop after the scan.

Common mistakes and edge cases

Wrong comparison direction

Using > when you needed < gives next-smaller when you wanted next-greater. Anchor on the rule "pop when you find the answer" and derive the operator from the question every time.

Storing values instead of indices

You lose the ability to compute a distance or width. Any problem that asks "how far" or "how wide" needs indices on the stack. Default to indices.

Handling ties (> vs >=)

Equal values are the classic edge case. Whether you pop on equality changes whether "next greater" means strictly greater or greater-or-equal. Read the problem, then pick > or >= deliberately, and test an input with duplicates.

Forgetting the leftovers

Elements still on the stack at the end never found their answer. Make sure your initial fill value (-1, 0, or infinity) is the correct "no answer" result, or add a sentinel to flush them.

Circular arrays

For "next greater in a circular array" (LC 503), iterate twice over the indices using i % n and only push during the first pass. The second pass resolves elements that wrap around.

What interviewers actually look for

The monotonic stack is a favorite interview pattern precisely because the brute force is so obvious. Anyone can write the O(n²) double loop. The signal the interviewer is watching for is whether you recognize the "next greater / next smaller" shape and reach for the stack, then explain the amortized O(n) correctly.

Say the invariant out loud before you code: "I will keep a stack of indices whose next greater element I have not found yet. When a bigger value arrives, it resolves everything smaller on top." That single sentence tells the interviewer you understand the data structure, not just the syntax, and it makes the code almost write itself.

Then defend the complexity: "The inner while loop looks quadratic, but each index is pushed once and popped once across the whole scan, so it is O(n) amortized." Naming the pushed-once, popped-once argument is the difference between reciting a solution and demonstrating that you actually understand why it is fast.

Related patterns on Expora

The monotonic stack is one of the core patterns that show up across coding interviews. For the full map, the 7 algorithm patterns behind 80% of interview problems places it next to sliding window, two pointers, and dynamic programming.

If you are still deciding which technique a problem needs, the coding interview patterns guide walks through the structural signal that triggers each one.

The fastest way to trust the pushed-once, popped-once argument is to watch the stack fill and drain. The visual algorithm debugger lets you step through the execution with the stack, the scan pointer, and the result all visible at once.

Frequently asked questions

Expora

No credit card required · Early access