Monotonic Stack
A stack with a rule: values are always non-increasing or non-decreasing. Each element enters once and leaves once — giving O(n) solutions to problems that look like they need O(n²) comparisons.
Find next greater for every element with nested loops — O(n²). Monotonic stack — O(n)
The invariant: the stack is always sorted. When a new element violates the sort order, pop everything it violates — those elements have just found their answer (the current element). Each element enters once and leaves once → 2n ops → O(n).
Two Monotonic Stack Types
The direction of the invariant determines what question you're answering.
Elements wait on the stack until something larger arrives. That larger element IS their next greater. Popping resolves them.
Elements wait until something smaller arrives (for next-smaller). Or greedily remove larger elements to minimize a number.
The 3-Step Framework
The same skeleton works for every monotonic stack problem.
Decreasing: 'next/previous GREATER element', 'how long until X exceeds Y', 'largest rectangle'. Increasing: 'next/previous SMALLER element', 'smallest possible result', 'remove large elements greedily'.
# Next GREATER -> decreasing stack # while stack and nums[stack[-1]] < nums[i]: # Next SMALLER -> increasing stack # while stack and nums[stack[-1]] > nums[i]:
Inside the while loop: pop the index, compute the answer for that index (usually using the current index for distance or current value for NGE), write to result. Then push the current index.
while stack and nums[stack[-1]] < nums[i]: # decreasing
idx = stack.pop()
result[idx] = nums[i] # current = NGE
# or: result[idx] = i - idx # distance
stack.append(i) # push index (not value)Elements remaining on the stack after the loop have no next greater/smaller — leave result at default (-1 or 0). For Remove K Digits: trim k from end. For contribution problems: boundaries are array edges.
# NGE: remaining have no NGE, result stays -1
return result
# Remove K Digits: k removals still needed
if k: stack = stack[:-k]
return ''.join(stack).lstrip('0') or '0'Pattern Recognition
Two seconds to identify monotonic stack in an interview.