Foundation · Module 11 · Lesson 4

Monotonic stack

Next greater/smaller and contribution ranges.

15–25 min readLesson 61 of 123

Lesson 61 of 123

1d streak

Monotonic Stack: Finding Next Greater / Smaller Elements

A Monotonic Stack maintains its elements in strictly sorted order (either strictly increasing or strictly decreasing). It solves problems of the form: "For each element, find the nearest element to its right or left that is greater or smaller than it" in $O(n)$ total time instead of brute-force $O(n^2)$.

Next Greater Element (NGE) Trace for [2, 1, 2, 4, 3]
Goal: Find next greater element to the right for each number.

Scan from Right to Left (index 4 -> 3 -> 2 -> 1 -> 0):
1. Element 3 (idx 4): Stack is empty -> NGE is -1. Push 3.           Stack: [ 3 ]
2. Element 4 (idx 3): Top 3 is smaller -> Pop 3. Stack empty -> -1. Push 4. Stack: [ 4 ]
3. Element 2 (idx 2): Top 4 is greater -> NGE is 4. Push 2.           Stack: [ 4, 2 ]
4. Element 1 (idx 1): Top 2 is greater -> NGE is 2. Push 1.           Stack: [ 4, 2, 1 ]
5. Element 2 (idx 0): Top 1 is <= 2 -> Pop 1. Top 2 is <= 2 -> Pop 2.
                      Top 4 is greater -> NGE is 4. Push 2.           Stack: [ 4, 2 ]

Final Output: [4, 2, 4, -1, -1]
Total Time: Every element is pushed once and popped at most once = O(n) linear time!
NextGreaterElement.java
public int[] nextGreaterElements(int[] nums) {
    int n = nums.length;
    int[] result = new int[n];
    Deque<Integer> stack = new ArrayDeque<>(); // stores values (or indices)

    for (int i = n - 1; i >= 0; i--) {
        // Pop all elements that are smaller than or equal to current number
        while (!stack.isEmpty() && stack.peek() <= nums[i]) {
            stack.pop();
        }
        result[i] = stack.isEmpty() ? -1 : stack.peek();
        stack.push(nums[i]);
    }
    return result;
}

Use it when

Use a Monotonic Stack when you need the nearest boundary (greater or smaller element) to the left or right: Daily Temperatures, Stock Span, Next Greater Element, Largest Rectangle in Histogram.

Reconsider when

Reconsider when you need the global maximum or minimum across an entire window (use a Monotonic Deque or Heap instead).

Cost Model

Complexity & Trade-offs

Full scan
O(n)
O(n)
Every index is pushed and popped at most once.

When to use it

  • Nested parsing, undo, arrival order, buffering, and nearest-greater queries.
  • BFS frontiers and producer/consumer scheduling.
  • Maintaining range extremes or constrained access.

Common mistakes

  • Reading from an empty structure.
  • Confusing the logical front with an array index in a circular buffer.
  • Missing the amortized argument for transfers or monotonic pops.

Practice prompts

  • Reproduce the worked Monotonic stack example without looking at the trace.
  • Change one input condition and explain whether the Monotonic stack invariant still holds.
  • Implement the approach, derive its cost, and compare it with a straightforward baseline.

Mastery check

Can you derive it instead of memorizing it?

State the invariant before looking at code.
Explain why every transition is safe.
Construct a worst-case input.
Name one alternative and its trade-off.