Layers of Logic

Pattern 04

Monotonic Stack

Keep unresolved positions in value order so a new item can answer several of them at once.

Complete moduleO(n) timeO(n) extra space

Built from

ArrayStack

Read the constraints before choosing the technique

Next or previous greater/smaller item

Each position waits for the first later item that defeats it.

Distance to the next qualifying item

The stack should store positions so their difference is available.

The slow solution scans rightward from every index

A stack can preserve only candidates that still lack an answer.

Histogram width or boundary problems

Popping can reveal both the first smaller boundary and the previous surviving boundary.

Cases that look similar but need another approach

The maximum of a moving window is required

Expired items must also leave from the front, which a stack cannot do.

Use Monotonic deque

Items are compared with a running total rather than one another

Nothing causes unresolved candidates to be popped.

Use Sliding window or prefix sums

Every greater item must be returned

Popping after one answer would discard information the output still needs.

Use Nested enumeration or another output-sensitive method

The ideas the code depends on

  1. The stack is ordered because weaker candidates leave

    For a decreasing stack, a larger incoming value repeatedly removes smaller top values. Once it stops, the remaining top and everything below it are at least as large.

  2. Store indices, not just values

    The index gives back both nums[index] and a distance such as current − index. The value alone cannot recover position.

  3. Nested loops do not make this quadratic

    Each index is pushed once and popped at most once. The total number of stack operations is at most 2n.

Turn the invariant into a repeatable process

  1. 01

    Visit positions from left to right.

  2. 02

    While the stack is non-empty and the current value answers its top, pop that position.

  3. 03

    Write the popped position’s value, distance, or boundary answer.

  4. 04

    Push the current position because it now waits for a future answer.

  5. 05

    Leave the default result for any positions still unresolved at the end.

Common forms of the pattern

FormUse it forWhat changes
Answer on popNext greater value or next warmer dayThe incoming item supplies the popped item’s answer.
Answer on pushPrevious greater item and stock spanAfter weaker items leave, the surviving top is the current answer.
Boundary on popLargest rectangle or trapped waterThe incoming index is the right boundary; the new top helps define the left.
TimeO(n)
Extra spaceO(n)

Every index enters the stack once and can leave it only once, so all executions of the inner while loop total at most n.

Worked form

Daily temperatures

For each day, return how many days pass before a warmer temperature; return zero when none exists.

Daily temperatures

int[] daysUntilWarmer(int[] temperature) {
    int[] answer = new int[temperature.length];
    Deque<Integer> stack = new ArrayDeque<>();

    for (int i = 0; i < temperature.length; i++) {
        while (!stack.isEmpty()
                && temperature[i] > temperature[stack.peek()]) {
            int earlier = stack.pop();
            answer[earlier] = i - earlier;
        }
        stack.push(i);
    }
    return answer;
}

Common implementation mistakes

  • Peeking before checking that the stack is non-empty
  • Storing values when the answer requires distance
  • Using < where duplicates require <=, or the reverse
  • Calling the algorithm O(n²) merely because the loops are nested

What stays the same—and what changes

These are not five unrelated solutions. Each problem preserves the movement rule and changes one part of the state or answer.

Next Greater Element

Easy

Write the incoming value rather than a distance.

Stock Span

Medium

Pop previous smaller prices and answer from the surviving boundary.

Remove K Digits

Medium

Pop larger earlier digits while removals remain.

Largest Rectangle in Histogram

Hard

Use both boundaries exposed when a bar is popped.

Trapping Rain Water

Hard

Treat a popped bar as the bottom of a basin.

Check the movement rule, not a memorized line

Why is the standard monotonic-stack scan O(n) despite its inner while loop?