PrepStack · Markdown HTML

Monotonic stack for nearest greater/smaller

Stack and monotone deque · HTML

Formal shape

Scan i. While a[i] satisfies resolve(a[stack[-1]],a[i]), pop j and finalize its right boundary as i. Push i afterward, preserving the chosen value monotonicity.

Recognition signals

False friends

SignalWhy it is different
Arbitrary range-maximum queriesA monotonic stack finds nearest boundaries, not general online interval extrema.
Sliding-window extremaCandidates also expire by position, requiring a two-ended monotonic deque.

Core invariant

Stack indexes increase, their values are monotone in the chosen direction, and every stored index has not yet encountered a right-side item that resolves it.

State, transition, and processing order

ItemDefinition
StateIndex stack, current index/value, strictness choice (> versus ≥), and result array.
TransitionRepeatedly pop candidates resolved by the new value and write their answers; when no more resolve, push the current index.
Frontier / orderAll nondominated candidates still lacking a right answer; a popped candidate can never matter again.

Python skeleton

def next_strictly_greater(values):
    answer = [-1] * len(values)
    stack = []  # indexes, values strictly decreasing
    for i, value in enumerate(values):
        while stack and values[stack[-1]] < value:
            j = stack.pop()
            answer[j] = i
        stack.append(i)
    return answer

Correctness sketch

  1. When j pops, the current value is greater, and every earlier scanned value while j remained on stack failed to pop it, so i is its first strictly greater position.
  2. Unpopped candidates remain value-monotone and every candidate dominated by the new value has been resolved.
  3. Each index enters once and exits at most once; any index left at end truly has no greater value to its right.

Complexity

TimeSpaceParameters
O(n)O(n)Despite the nested while, each index is pushed and popped at most once over the complete scan.

Edge cases

Error patterns

PatternWhy it fails / fix
Storing values when indexes are neededDistances, boundaries, and duplicate handling usually require indexes.
Swapping < and <= casuallyDuplicates may be double-counted or omitted; strictness must follow the definition.
Calling the nested loop O(n²)Use the at-most-one-pop-per-index amortized argument.

Selection and exclusion rules

RelationTemplateBoundary
no-expiration special caseMonotonic deque for window extremaCandidates are removed only by dominance, never by the left boundary.
aggregation after boundariesPrefix sum / range aggregationThe stack finds influence intervals and prefixes evaluate interval quantities.
analogous monotone eliminationOpposite-direction two pointersBoth safely discard candidates but represent different candidate spaces.

Original micro-example

PartDetail
ResultResult indexes are [3,2,3,-1].
SetupValues [5,2,4,7]; find the first strictly greater index to the right.
Trace4 pops index of 2; 7 later pops indexes of 4 and 5.

Recall prompts

My notes