PrepStack · Markdown HTML

Monotonic deque for window extrema

Stack and monotone deque · HTML

Formal shape

Deque indexes increase by position and their values are monotone in the target direction. At i, remove heads with index≤i-k, pop tail candidates no better than a[i], then append i.

Recognition signals

False friends

SignalWhy it is different
Nearest greater elementWithout positional expiration, a monotonic stack is more direct.
Window sum or frequencyReversible aggregates need only an ordinary sliding window, not dominance eviction.

Core invariant

Deque indexes strictly increase and lie in the current window; values are monotone, the front is the current extremum, and every tail-popped index can never beat the newer index in any future shared window.

State, transition, and processing order

ItemDefinition
StateIndex deque, current index i, window width k, and output or DP state.
TransitionRemove expired heads, remove tail candidates dominated by the current value, append i, and read the front once the window matures.
Frontier / orderA Pareto chain of current-window indexes that can still become an extremum now or in a future overlapping window.

Python skeleton

from collections import deque

def window_max(values, k):
    if k <= 0 or k > len(values):
        return []
    dq, answer = deque(), []
    for i, value in enumerate(values):
        while dq and dq[0] <= i - k:
            dq.popleft()
        while dq and values[dq[-1]] <= value:
            dq.pop()
        dq.append(i)
        if i >= k - 1:
            answer.append(values[dq[0]])
    return answer

Correctness sketch

  1. Head expiration keeps every stored index inside the current window.
  2. If an older value is no larger than the new value, it expires sooner and is never better in a shared future window, so tail removal is safe.
  3. Remaining values are monotone; the front is unexpired and undominated, hence exactly the window maximum.

Complexity

TimeSpaceParameters
O(n)O(k)Each index enters once and leaves from one end at most once; the deque stores at most k current-window indexes.

Edge cases

Error patterns

PatternWhy it fails / fix
Storing values instead of indexesExpiration cannot be detected and duplicate values cannot be distinguished.
Using < i-k for expirationIndex i-k is already outside [i-k+1,i], so the comparison must include equality.
Reversing tail monotonicityFor maxima, remove tail values no greater than the new value.

Selection and exclusion rules

RelationTemplateBoundary
extremum state componentFixed-size sliding windowA fixed window moves from an invertible sum to noninvertible min/max.
extrema/prefix enhancementVariable-size sliding windowThe window must retain an extremum or optimal historical prefix.
ordered-candidate alternativeTop-K bounded heapSeveral priority-ranked candidates are needed rather than one dominance chain.
same container, different invariant0-1 BFSDo not confuse priority buckets with a window-extrema deque.

Original micro-example

PartDetail
ResultThe two window maxima are [3,3].
SetupValues [2,1,3,2], k=3; report each window maximum.
TraceAt 3, pop both 1 and 2 from the tail, leaving index 2; the next 2 joins but 3 remains front.

Recall prompts

My notes