Monotonic Stack & Queue Patterns

Lesson, slides, and applied problem sets.

View Slides

Lesson

Monotonic Stack & Queue Patterns

Why this module exists

Monotonic structures give you O(n) solutions for problems that look like nested loops. The core idea: keep a stack or deque in sorted order so each index is pushed and popped at most once.


Monotonic stack (next greater / smaller)

Maintain a stack of indices with decreasing values.

When you see a larger value, pop until the stack is valid. Each popped index has just found its next greater element.

func nextGreater(nums []int) []int {
    n := len(nums)
    res := make([]int, n)
    for i := range res {
        res[i] = -1
    }
    stack := []int{}
    for i, v := range nums {
        for len(stack) > 0 && nums[stack[len(stack)-1]] < v {
            j := stack[len(stack)-1]
            stack = stack[:len(stack)-1]
            res[j] = v
        }
        stack = append(stack, i)
    }
    return res
}

Largest rectangle in histogram

Keep a stack of increasing heights. When a new bar is lower, pop and compute the rectangle with the popped height as the limiting height.

Key trick: append a sentinel height 0 to flush the stack at the end.


Monotonic deque (sliding window max)

For a window of size k:

  • Pop from back while new value is larger
  • Pop from front if it is outside the window
  • Front is always the maximum

This gives O(n) total time for all windows.


What you will build

  • Next greater element with a monotonic stack.
  • Largest rectangle in a histogram using stack boundaries.

Module Items