Overview
A deque (double-ended queue) supports insertion and removal at both the front and the back in O(1). It generalizes both a stack and a queue.
Its star use in algorithms is the monotonic deque: keep indexes in the deque so their values are always decreasing (or increasing). Then the maximum (or minimum) of a sliding window is at the front, and each element is added and removed at most once, giving O(n) for all windows.
You can draw from the top or bottom and place cards on either end. A monotonic deque is like keeping only cards that could still become the highest card in view, discarding weaker cards as soon as a stronger one arrives after them.
When to use it
- You need both stack-like and queue-like operations.
- Maximum or minimum of every sliding window.
- 0-1 BFS: edges of weight 0 go to the front, weight 1 to the back.
- Palindrome checks and problems that consume from both ends.
Problem patterns it solves
Recognize it when: max or min of each window of size k.
- 239. Sliding Window Maximum
- 1438. Longest Continuous Subarray With Absolute Diff <= Limit
- 2398. Maximum Number of Robots Within Budget
Recognize it when: dp[i] = max(dp[j]) + x for j in the last k indexes.
- 1696. Jump Game VI
- 1425. Constrained Subsequence Sum
- 862. Shortest Subarray with Sum at Least K
Recognize it when: shortest path where edges cost 0 or 1.
- 1368. Minimum Cost to Make at Least One Valid Path in a Grid
- 2290. Minimum Obstacle Removal to Reach Corner
Recognize it when: take from either end, rotate, or simulate a deck.
- 950. Reveal Cards In Increasing Order
- 1423. Maximum Points You Can Obtain from Cards
- 641. Design Circular Deque
Where it is used in real software
Java's ForkJoinPool gives each worker a deque: it pushes and pops its own tasks at one end while idle workers steal from the other end.
New actions are pushed on one end and the oldest are dropped from the other when the history limit is reached.
Rolling max and min over the last N data points (for alerts or trading signals) use monotonic deques.
Tab switchers and recent-items lists add and remove at both ends.
Key terms
- offerFirst / offerLast
- Insert at front / back (unshift / push in JS).
- pollFirst / pollLast
- Remove from front / back (shift / pop in JS).
- Monotonic deque
- Values of stored indexes are kept strictly decreasing (for max) or increasing (for min).
- Expired index
- An index that has left the window: index <= i - k.
Sliding window maximum with a monotonic deque
- 1Store indexes, not values
Indexes let you tell when an element has left the window.
- 2Remove expired front
If deque.front <= i - k, remove it from the front.
- 3Remove smaller values from the back
While nums[deque.back] <= nums[i], pop the back. Those elements can never be a maximum again, because nums[i] is larger and will stay in the window longer.
- 4Push i to the back
The deque stays decreasing from front to back.
- 5Read the answer
Once i >= k - 1, nums[deque.front] is the window maximum.
STEP 1i = 1: 3 >= 1, pop index 0. Deque = [1] (value 3).
Deque state for sliding window maximum
nums = [1, 3, -1, -3, 5, 3, 6, 7], k = 3
| i | nums[i] | Deque (indexes) | Deque values | Window max |
|---|---|---|---|---|
| 0 | 1 | [0] | [1] | - |
| 1 | 3 | [1] | [3] | - |
| 2 | -1 | [1, 2] | [3, -1] | 3 |
| 3 | -3 | [1, 2, 3] | [3, -1, -3] | 3 |
| 4 | 5 | [4] | [5] | 5 |
| 5 | 3 | [4, 5] | [5, 3] | 5 |
| 6 | 6 | [6] | [6] | 6 |
| 7 | 7 | [7] | [7] | 7 |
NOWi: 0 | nums[i]: 1 | Deque (indexes): [0] | Deque values: [1] | Window max: -
Output [3, 3, 5, 5, 6, 7]. Each index enters and leaves the deque once, so the whole run is O(n) instead of O(n x k).
Implementation
// A head index keeps shift() O(1) for this algorithmfunction maxSlidingWindow(nums, k) { const dq = []; let head = 0; const result = []; for (let i = 0; i < nums.length; i++) { if (head < dq.length && dq[head] <= i - k) head++; // expired front while (dq.length > head && nums[dq.at(-1)] <= nums[i]) dq.pop(); // weaker back dq.push(i); if (i >= k - 1) result.push(nums[dq[head]]); } return result;} // 1438: two deques track window max and min at the same timefunction longestSubarray(nums, limit) { const maxDq = [], minDq = []; let left = 0, best = 0; for (let right = 0; right < nums.length; right++) { while (maxDq.length && maxDq.at(-1) < nums[right]) maxDq.pop(); while (minDq.length && minDq.at(-1) > nums[right]) minDq.pop(); maxDq.push(nums[right]); minDq.push(nums[right]); while (maxDq[0] - minDq[0] > limit) { if (maxDq[0] === nums[left]) maxDq.shift(); if (minDq[0] === nums[left]) minDq.shift(); left++; } best = Math.max(best, right - left + 1); } return best;}Complexity and performance
ArrayDeque, circular buffer, or doubly linked list.
Each index pushed and popped once.
At most one window of indexes.
Trade-offs
A heap gives O(n log k) and needs lazy deletion of expired items. The monotonic deque gives O(n) and is simpler once understood.
push and pop are O(1), but shift and unshift are O(n). Use a head index, or a circular buffer for heavy use.
Variants and related techniques
Keep values increasing to get window minimums.
For each edge of weight 0, add the neighbor to the front; for weight 1, add it to the back. Gives shortest paths in O(V + E).
Fixed-capacity deque on a ring buffer.
Common mistakes
- Storing values instead of indexes.
Fix: Without indexes you cannot detect when the front has left the window.
- Using < instead of <= when popping.
Fix: Either works for correctness in max problems, but <= keeps the deque smaller; be consistent with duplicates when storing values.
- Recording answers before the first full window.
Fix: Only record when i >= k - 1.
Interview questions
Why can we discard smaller elements behind a new larger one?
The new element is larger and entered later, so it will remain in the window at least as long as the smaller ones. The smaller ones can never be the maximum again.
What is 0-1 BFS?
A shortest-path algorithm for graphs with edge weights of only 0 or 1, using a deque instead of a priority queue: 0-weight neighbors go to the front and 1-weight neighbors to the back.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| 641. Design Circular Deque | Medium | Implementation. |
| 239. Sliding Window Maximum | Hard | Monotonic deque. |
| 1438. Longest Continuous Subarray With Absolute Diff <= Limit | Medium | Two deques for max and min. |
| 1696. Jump Game VI | Medium | DP with deque. |
| 862. Shortest Subarray with Sum at Least K | Hard | Deque over prefix sums with negatives. |