Unit 1.6 · about 5 h
93 / 324Stacks, queues, deques and monotone structures
Stacks suspend work until its context arrives; queues order it fairly. Their monotone variants turn quadratic scans into single passes across parsing, scheduling and windows.
- implement
You can now
- Implement stack, queue, deque and circular buffer from the contracts with \(O(1)\) bounds.
- Derive the \(2n\) push/pop bound for monotone stacks and deques and state the maintained order.
- Diagnose empty-structure, order and expiry defects (values versus indices).
Covers
- Stacks, queues, circular buffers and deques
- Monotone stacks and deques
Study, in this order
4 steps
- Stacks and the call stack analogyDSA Handbook - Foundations and linear patterns
The LIFO contract; The call stack is the same data structure; LC 20 the deferred-match validator; What it actually costs (
pushamortized \(O(1)\), LC 20 \(O(n)\) time and space) - Queues, deques, and circular buffersDSA Handbook - Foundations and linear patterns
The FIFO contract; The deque adds the back end; The circular buffer fixes the capacity; Why the patterns chapters teach the rest (LC 232 amortized queue); What it actually costs (
list.pop(0)\(O(n)\) againstdeque\(O(1)\)) - Monotonic stackDSA Handbook - Foundations and linear patterns
The pattern (pop-while-violating then push); Why the work stays linear (\(2n\) aggregate); Worked example LC 739 on
[73, 74, 75, 71, 69, 72, 76, 73]; Largest rectangle: the sentinel-pop trick; Two pitfalls (indices, not values) - Monotonic dequeDSA Handbook - Foundations and linear patterns
The invariant (decreasing indices, front is the \(\operatorname{argmax}\)); The pattern (drop-front, pop-tail, push, emit); Worked example LC 239 on
[1, 3, -1, -3, 5, 3, 6, 7]with \(k = 3\); What it actually costsDepth · The cost table lists the max-heap with lazy deletion as \(O(n \log k)\) beside \(O(n)\) space. The space column is right: stale entries stay buried, so the heap can hold \(n\) entries and its worst case is \(O(n \log n)\).
Focus on
- Each index enters and leaves once: at most \(2n\) stack ops and at most \(2n\) deque ops. That is the whole linearity proof.
- Monotone structures store indices: values cannot report expiry.
- Deque order per slide: drop the expired front, pop smaller backs, push, emit the front.
- Python
listis the stack andcollections.dequeis the queue. Swapped roles cost \(O(n)\) per op at the wrong end.
Reproduce closed-book
[1, 3, -1, -3, 5, 3, 6, 7] with \(k = 3\) output [3, 3, 5, 5, 6, 7]. Differential-test it against the \(O(nk)\) brute force with Hypothesis (lengths up to 50, \(k\) up to 10, derandomize, max_examples=200) in Python 3.13: expect 1 passed.Traps
- Storing values instead of indices: equal values from different positions become indistinguishable and expiry breaks.
- Emitting before pushing or popping the wrong end: the order is drop-front, pop-back, push, emit.
list.pop(0)as a queue (about 45x slower thandequeper drain at \(n = 20000\) on the stated CPU and Python 3.13.14), and recursion past the default limit of 1000 frames, which raisesRecursionErrorinstead of growing.
Practice
LeetCode 20: Valid Parentheses
Implement the deferred-match validator with the terminal empty check. Judge with the Examples (), ()[]{} and ([)].
After submitting, compare against the handbook stacks section LC 20: the deferred-match validator.
LeetCode 739: Daily Temperatures
Implement the pop-while-smaller template storing indices. Judge with the Examples [73, 74, 75, 71, 69, 72, 76, 73] and [30, 40, 50, 60].
After submitting, compare your trace against the handbook monotonic-stack worked example on the same input.
LeetCode 239: Sliding Window Maximum
Attempt cold with hidden tags. Implement the monotone deque and judge with the Example [1, 3, -1, -3, 5, 3, 6, 7], \(k = 3\) giving [3, 3, 5, 5, 6, 7].
After submitting, read the AlgoMaster Sliding Window Maximum write-up (https://algomaster.io/learn/dsa/sliding-window-maximum) and the handbook monotonic-deque cost table.
Self-test
-
Prove the monotone stack is \(O(n)\).
Each element is pushed once and popped at most once, so the whole run performs at most \(2n\) stack operations (aggregate method). -
Argue the two-stack queue is amortized \(O(1)\).
Each element moves from inbox to outbox at most once, so \(n\) operations move at most \(2n\) elements. -
Why must the deque hold indices?
Expiry compares positions against \(i-k+1\). Values alone cannot tell a live equal from an expired one. -
What does the heap alternative cost on sliding maximum, and when does the deque win?
With lazy deletion, \(O(n \log n)\) in the worst case: on increasing input no stale entry ever reaches the top, so the heap grows to \(n\) entries. A heap or balanced tree with real deletion gets \(O(n \log k)\). The deque's \(O(n)\) beats both, and the gap grows with \(k\).
Completion criterion
Stop when
All three are accepted and your deque emits the worked trace exactly, with the \(2n\) argument written beside it.
Mark passed, then open 1.7 Only mark this when you can do it without notes.Leads to
- 1.7 Two pointers and sliding windows Sliding windows reuse the deque discipline with a different trigger.
- 2.6 Heaps and priority queues Heaps are the \(O(n \log n)\) lazy-deletion alternative the deque beats on windows.
Comes after
- 1.2 Aggregate, accounting and potential amortized analysisThe two-stack queue is the next amortized argument.
- 1.4 Arrays, strings, locality and linked structuresStacks and queues pick their backing layout from this unit.
- 1.5 Hash tables: collisions, load factor, resizing and tombstonesThe LC 380 trick pairs a hash map with a dynamic array.
- 1.7 Two pointers and sliding windowsTrapping Rain Water meets both windows and monotone stacks.
Resources for this unit
- DSA Handbook - Foundations and linear patterns Study Part 0, Part 1, Part 3 and Part 4 in order, plus the Part 5 Linked-list fundamentals chapter. Use the routing-rule pages for arrays versus lists, map choice, stack versus queue, two pointers, sliding windows and prefix methods before seeing solved code.
Also in this section
- AlgoMaster DSA - linear structures slice Attempt Design HashMap, Longest Substring Without Repeating Characters and Sliding Window Maximum cold. Hide tags, state the invariant first, and add randomized operation histories to Design HashMap.
- MIT 6.042J - asymptotics and invariants Use the asymptotics, state-machine invariants and proof-method readings when a cost or correctness argument is weak. Solve only the matching problems.
- Algorithms lecture notes - amortized analysis and hashing Use note 9 Amortized Analysis for the summation, taxation, charging and potential-function proofs, and note 5 Hashing for chaining, universal hashing and open-addressing analysis, when the handbook treatment is too brief for a proof.
- Algorithmica - memory and data layout Read the memory hierarchy, cache and complexity-model chapters, then measure one contiguous-versus-linked and one hash-versus-ordered workload crossover.
- NeetCode - unseen linear problems Use only for two tag-hidden transfer problems after the AlgoMaster slice. Do not start another full roadmap or watch a solution before the attempt is complete.
- Hypothesis documentation - Quickstart and stateful testing Follow Quickstart for
@givenstrategies and the pytest combination, Configuring test settings formax_examplesandderandomize, then Rule-based state machines (rule,precondition,invariant,run_state_machine_as_test) for randomized operation histories againstdictanddequeoracles. - CPython source - list and dict objects Read
list_resizeinObjects/listobject.cfor the growth formula and pattern comment, and theUSABLE_FRACTIONdefinition, perturbation-probing comment and dummy-entry handling inObjects/dictobject.c. Read the cited functions and comments only.