STAQ-6

Monotonic queue

Stacks and queuesLesson 6 of 614 min

A monotonic queue is a deque whose values always go down from front to back. It answers “what is the biggest value in this window?” as the window slides along a list, in O(1) per step on average.

The biggest value in a moving window

A window is a run of k values next to each other in a list (ARRS-3). Slide it one place at a time from the start to the end, and report the biggest value in each position. For [4, 2, 12, 3, 8, 5, 1, 7] and k = 3, the answers are [12, 12, 12, 8, 8, 7].

Calling max on each window costs k steps per window, so O(n × k) in total. A running sum can be updated when a value leaves the window, but a maximum cannot: when the biggest value leaves, you do not know the next biggest.

A deque kept in order

Keep a deque of places. A value is worth keeping only if it might still become the biggest in some later window. When a new value x arrives, every older value that is <= x can never be the biggest again: x is at least as big, and stays in the window longer. So remove them from the back.

Each step does three things:

  • remove places from the back while their values are <= x, then add the new place at the back;
  • remove the front place if it has slid out of the window;
  • once the first window is complete, report the value at the front.
FIG STAQ-6.1Biggest value in each window of 3
a
4
2
12
3
8
5
1
7
deque
empty
places in the deque: none
maxima
none yet
1/21

Find the biggest value in every window of 3 values in a row. The deque holds places whose values go down from front to back. The front is always the biggest.

Step 1 of 21

dq is a collections.deque of places. Here are the first two parts of the step, for place i with value x:

while dq and a[dq[-1]] <= x:
    dq.pop()              # can never be the biggest again
dq.append(i)
if dq[0] <= i - k:        # the front has left the window
    dq.popleft()

The third part, reporting a[dq[0]] once i reaches k - 1, is left to STAQ-P6.

Only one place can leave the front per step, because the window moves one place at a time. That is why a single if is enough there, while the back needs a while.

Why it is O(n)

The same counting as lesson 5: each place is added to the deque once and removed at most once, from one end or the other. So the whole run does n additions and at most n removals, at most 2n steps in all: O(n), whatever k is. After each step the deque holds at most k places.

Other ways, and their cost

Ways to find the maximum of every window
MethodTimeNotes
max of each windowO(n × k)Fine for small k.
A heap with old entries removed laterO(n log n)Uses heaps (HEAP). Keep (value, place) pairs and drop a top that has left the window.
Monotonic dequeO(n)The best possible: every value must be read once.

The monotonic deque also speeds up some dynamic programming, where each answer is the best of the last k answers. You will meet that in DYNP.

Now try STAQ-P6, Biggest in each window.

STAQ-6 counts as completed once you step through the figure to the last step.