For each daily temperature, the next warmer day may be far ahead. Rescanning the suffix repeats the same comparisons. A monotonic stack keeps only unresolved days, and one warmer value can settle several of them at once.

A monotonic stack stores indices while their values remain ordered. For a next-greater query, values are non-increasing from bottom to top. An arriving value pops every smaller value above it and becomes the next greater value for each popped index. Every index is pushed once and removed at most once.

A monotonic deque adds window expiry. New candidates enter at the back, dominated candidates leave from the back, and expired indices leave from the front. Storing indices makes both expiry and duplicate identity explicit.

Visualization

The trace uses daily temperatures [73, 74, 75, 71, 69, 72, 76, 73]. At 72, the stack pops 69 and 71, then becomes [75, 72] from bottom to top. At 76, it pops 72 and 75; 74 was already popped when 75 arrived. The six popped temperatures are 73, 74, 69, 71, 72, and 75, each in its own frame. Converting each resolved next index to nextIndex - currentIndex gives the Daily Temperatures waits [1, 1, 4, 2, 1, 1, 0, 0]. The charge counter shows the global bound: eight pushes and six pops over the whole scan.

The stack holds unanswered indices whose values are non-increasing from bottom to top. When a[i] pops index j, no position between j and i held a greater value — such a value would already have popped j. Therefore i is the nearest qualifying index to the right. Entries left after the scan have no greater value to their right.

The deque keeps the same monotone contents but adds a second exit. Values decrease from front to back; the front is always the current window maximum. Each new index i drops the front if it has slid out of the window, then pops from the back while a[back] <= a[i]: the incoming value is at least as large, and an equal newer index dominates because it expires later. Indices are the standard representation because the expiry check is direct; a value-only variant needs the departing value and may preserve equal entries separately or compress them into counts.

Each index is pushed once and removed at most once. Charge a removal to that index’s earlier push and no index can be charged twice, even though one arriving value may trigger several pops.

Complexity
n
number of elements in the scanned sequence

When the Invariant is Set Wrong

The monotone direction must match the query. A non-increasing stack with a < pop condition finds the next greater value. Reverse the invariant and it answers the opposite relation, leaving a different set of entries unresolved. Exact expected outputs over ordered, mixed, and duplicate inputs catch this mistake better than shape-only assertions.

Strictness decides what equal values mean. With [2, 1, 2], < keeps the older equal candidate while <= lets the newer one replace it. The choice affects both the reported relation and how long a deque candidate survives.

Window expiry is positional, so indices are the simplest deque representation. A value-only version needs the departing value and must either preserve equal entries or compress them into counts. Either representation loses element identity.

Diagram and C# Implementation

public static int[] MaxSlidingWindow(int[] a, int k) { var dq = new LinkedList(); // indices, values decreasing front to back var res = new int[a.Length - k + 1]; for (int i = 0; i < a.Length; i++) { if (dq.Count > 0 && dq.First.Value <= i - k) dq.RemoveFirst(); // front slid out of the window while (dq.Count > 0 && a[dq.Last.Value] <= a[i]) dq.RemoveLast(); // newer value is >= and expires later on ties dq.AddLast(i); if (i >= k - 1) res[i - k + 1] = a[dq.First.Value]; // front is the window max } return res; }

The pop comparison (`<` vs `<=`) sets tie handling. Both examples store indices so distances and window eviction stay recoverable.

Comparison

ApproachUse it for
Monotonic stack / dequeNearest greater/smaller or moving-window extrema
Indexed heap or periodically rebuilt heapWindow extrema when heap operations are already needed
Lazy-deletion heap without rebuildingAvoid when a long stream can accumulate expired entries
Two heaps / order-statistic treeWindow median / general k-th value

References