Pattern #16

Monotonic Stack

Important interview questions, thinking patterns, increasing vs decreasing stacks, and rules for solving monotonic stack problems in Go.

Must Solve

15 core questions — solve these first.

  1. 1.Daily Temperatures
    medium
  2. 2.Next Greater Element I
    easy
  3. 3.Next Greater Element II
    medium
  4. 4.Largest Rectangle in Histogram
    hard
  5. 5.Online Stock Span
    medium
  6. 6.Sum of Subarray Minimums
    medium
  7. 7.Remove K Digits
    medium
  8. 8.Trapping Rain Water
    hard
  9. 9.Asteroid Collision
    medium
  10. 10.Maximum Width Ramp
    medium
  11. 11.Next Greater Node In Linked List
    medium
  12. 12.132 Pattern
    medium
  13. 13.Remove Duplicate Letters
    medium
  14. 14.Sum of Subarray Ranges
    medium
  15. 15.Final Prices With a Special Discount in a Shop
    easy

Also Important

7 more questions worth practicing.

  1. 16.Buildings With an Ocean View
    medium
  2. 17.Number of Visible People in a Queue
    hard
  3. 18.Car Fleet
    medium
  4. 19.Shortest Unsorted Continuous Subarray
    medium
  5. 20.Maximum Subarray Min-Product
    medium
  6. 21.Steps to Make Array Non-decreasing
    medium
  7. 22.Total Steps to Make Array Non-decreasing
    medium

How to Think

  1. Need next greater?Monotonic Stack (Decreasing)
  2. Need next smaller?Monotonic Stack (Increasing)
  3. Need previous greater / smaller?Monotonic Stack
  4. Need nearest bigger / smaller element?Monotonic Stack
  5. Need distance to next bigger value?Store indexes (not only values)
  6. Need rectangle width?Previous Smaller + Next Smaller

Go Monotonic Stack Template

Next Greater Element Template (Decreasing Stack)

stack := []int{} // Stores indexes
result := make([]int, len(nums))

for i := 0; i < len(nums); i++ {
    // Current element solves any smaller elements waiting on stack
    for len(stack) > 0 && nums[i] > nums[stack[len(stack)-1]] {
        idx := stack[len(stack)-1]
        stack = stack[:len(stack)-1]
        result[idx] = nums[i] // Found Next Greater!
    }
    stack = append(stack, i) // Push current index
}

👉 Total Time: O(n) | Space: O(n) (Each element is pushed once & popped once)

Increasing vs Decreasing Monotonic Stack

Decreasing Stack [8, 6, 4, 2]
Use for: Next Greater Element
Why: Smaller elements wait for a bigger element to resolve them
Increasing Stack [1, 3, 5, 7]
Use for: Next Smaller Element
Why: Bigger elements wait for a smaller element to resolve them
Visual Memory Rule
Waiting values on stack:  [75, 71, 69]
Current element arrives:  72
Pop 69 & 71 → Push 72!
New stack state:          [75, 72]

💡 Golden Rule: "Keep only the unresolved values in sorted stack order, and let each new value resolve whatever it can."

Common Interview Mistakes

1. Wrong Stack Order Direction

Using an increasing stack when you need Next Greater (which requires a decreasing stack of waiting values).

2. Popping Only Once with IF

One new large element can resolve multiple smaller unresolved elements. Always use a while loop!

3. Storing Values Instead of Indexes

Storing values prevents calculating distance or width (i - stack.Top). Store indexes!

4. Assuming Nested Loop is O(n²)

Each element is pushed once and popped at most once, making the total work strictly O(n).

Interview Rules

  1. 1. Next greater? → Decreasing Monotonic Stack
  2. 2. Next smaller? → Increasing Monotonic Stack
  3. 3. Previous greater/smaller? → Monotonic Stack
  4. 4. Distance needed? → Store indexes on stack
  5. 5. Width needed? → Store indexes on stack
  6. 6. One current solves many previous? → Keep popping with while loop
  7. 7. Circular Array? → Process array twice (i % n)
  8. 8. Overall ComplexityO(n) time, O(n) space

Small Rules

  1. Rule 1:Each element is pushed once & popped once, total time is O(n).
  2. Rule 2: A nested `while` inside a loop does NOT mean O(n²) because items leave the stack only once.
  3. Rule 3: Store indexes when distance, width, or position is needed.
  4. Rule 4: Store values when only direct element comparison is needed.
  5. Rule 5: Circular array next greater element uses `i % n` over 2*n iterations.

Production Thinking

Stock Price MonitoringFor every stock price, find when next higher price occurs in O(n)

Server Load SpikesIdentify next time CPU load exceeds current threshold

Event Latency ThresholdsProcess request latency spikes without O(n²) forward scanning

E-Commerce Price DiscountsNext Smaller element for special discount applying

Remember This

Next Greater            → decreasing stack
Next Smaller            → increasing stack
Need distance           → store indexes
Current solves top?     → pop
Still solves top?       → keep popping
Then                    → push current
Each element            → push once, pop once (O(n))

💡 Golden Rule: "Keep only the unresolved values in sorted stack order, and let each new value resolve whatever it can."