A deque stores only the useful candidates for future windows — decreasing from front to back, so the front is always the current max.
Focus on recognizing:
“Max/min of every window” + O(n) required → monotonic deque of indices
Pattern 1: Sliding Window Maximum
[1,3,-1,-3,5,3,6,7], k=3 — watch small values get evicted so the front is always the max. Press ▶ to animate.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Sliding Window Maximum
For every window of size k sliding right across an array, report the maximum. A monotonic deque (kept strictly decreasing) stores candidate indices so the front is always the current window's max — giving O(n) total time.
Array [1,3,-1,-3,5,3,6,7], k=3. We keep a deque of indices in decreasing value order. When a bigger number arrives it kicks out all smaller ones behind it (they can never be the max again). The front index is evicted once it leaves the window. The L/R pointers are the window; the highlighted cell is its maximum. The output fills in as soon as the window has k elements.
1
for i in 0..n-1:
2
while deque and nums[back] < nums[i]: pop back
3
push i
4
if front <= i - k: pop front
5
if i >= k-1: output nums[deque[0]]
public int[] maxSlidingWindow(int[] nums, int k) {
Deque<Integer> deque = new ArrayDeque<>(); // indices
int n = nums.length;
int[] result = new int[n - k + 1];
for (int i = 0; i < n; i++) {
if (!deque.isEmpty() && deque.peekFirst() <= i - k)
deque.pollFirst(); // out of window
while (!deque.isEmpty()
&& nums[deque.peekLast()] < nums[i])
deque.pollLast(); // evict smaller
deque.offerLast(i);
if (i >= k - 1)
result[i - k + 1] = nums[deque.peekFirst()];
}
return result;
}from collections import deque
def max_sliding_window(nums, k):
dq = deque() # indices
result = []
for i, num in enumerate(nums):
if dq and dq[0] <= i - k:
dq.popleft() # out of window
while dq and nums[dq[-1]] < num:
dq.pop() # evict smaller
dq.append(i)
if i >= k - 1:
result.append(nums[dq[0]])
return resultvector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> dq; // indices
vector<int> result;
for (int i = 0; i < (int)nums.size(); i++) {
if (!dq.empty() && dq.front() <= i - k)
dq.pop_front(); // out of window
while (!dq.empty() && nums[dq.back()] < nums[i])
dq.pop_back(); // evict smaller
dq.push_back(i);
if (i >= k - 1)
result.push_back(nums[dq.front()]);
}
return result;
}function maxSlidingWindow(nums, k) {
const dq = []; // indices
const result = [];
for (let i = 0; i < nums.length; i++) {
if (dq.length && dq[0] <= i - k) dq.shift(); // expired
while (dq.length && nums[dq.at(-1)] < nums[i])
dq.pop(); // evict smaller
dq.push(i);
if (i >= k - 1) result.push(nums[dq[0]]);
}
return result;
}A value can never be a future max once something bigger arrives — evict it. Each index enters/leaves once ⇒ O(n).
Pattern 2: Sliding Window Minimum
Flip to an increasing deque — front is always the smallest in view.
⚠️ Animation & Content Notice
The animation work is not fully finished — some animations may have slight errors.
If there is a major error in the content or if the animation or content is difficult to understand, please contact us at rayyancodingschool@gmail.com.
Sliding Window Minimum
Find the minimum in every sliding window of size k. An increasing deque keeps the smallest at the front — evict useless larger elements.
Array: [8,5,10,7,9], k=3. Increasing deque of indices. Watch the answer array fill in as windows slide right.
1
deque = [] // indices, values increasing
2
for i in 0..n-1:
3
while back ≥ nums[i]: pop_back // can never be min
4
push_back(i)
5
if front ≤ i-k: pop_front
6
i ≥ k-1 → answer front value
Flip one comparison — keep the deque increasing:
public int[] minSlidingWindow(int[] nums, int k) {
Deque<Integer> deque = new ArrayDeque<>();
int[] result = new int[nums.length - k + 1];
for (int i = 0; i < nums.length; i++) {
if (!deque.isEmpty() && deque.peekFirst() <= i - k)
deque.pollFirst();
while (!deque.isEmpty()
&& nums[deque.peekLast()] > nums[i]) // flip!
deque.pollLast();
deque.offerLast(i);
if (i >= k - 1)
result[i - k + 1] = nums[deque.peekFirst()];
}
return result;
}from collections import deque
def min_sliding_window(nums, k):
dq = deque()
result = []
for i, num in enumerate(nums):
if dq and dq[0] <= i - k:
dq.popleft()
while dq and nums[dq[-1]] > num: # flip!
dq.pop()
dq.append(i)
if i >= k - 1:
result.append(nums[dq[0]])
return resultvector<int> minSlidingWindow(vector<int>& nums, int k) {
deque<int> dq;
vector<int> result;
for (int i = 0; i < (int)nums.size(); i++) {
if (!dq.empty() && dq.front() <= i - k)
dq.pop_front();
while (!dq.empty() && nums[dq.back()] > nums[i]) // flip!
dq.pop_back();
dq.push_back(i);
if (i >= k - 1)
result.push_back(nums[dq.front()]);
}
return result;
}function minSlidingWindow(nums, k) {
const dq = [];
const result = [];
for (let i = 0; i < nums.length; i++) {
if (dq.length && dq[0] <= i - k) dq.shift();
while (dq.length && nums[dq.at(-1)] > nums[i])
// flip!
dq.pop();
dq.push(i);
if (i >= k - 1) result.push(nums[dq[0]]);
}
return result;
}Max → evict SMALLER (
<). Min → evict LARGER (>). Everything else identical.
Why Store Indices, Not Values?
Indices answer two questions values cannot:
- Expiry —
index <= i − kmeans it left the window. - Value lookup —
nums[index]gives both at once.
Storing raw values makes expiry undetectable.
Common Mistakes
Evicting equal elements with strict <.
< keeps duplicates in the deque — harmless but wasteful; use <= if you prefer tighter deques. Just stay consistent between max/min versions.
Checking expiry after pushing instead of before.
The expired index must be removed before reading peekFirst() as the answer.
Using a heap “because it’s max queries”.
O(n log k) passes, but interviews ask for the O(n) deque when they say sliding window maximum.
Complexity
| Metric | Value |
|---|---|
| Time | O(n) — each index pushed/popped once |
| Space | O(k) — deque never exceeds window |
Premium Content
Unlock Sliding Window Maximum and all premium lessons with a subscription.
From ₹199.99/year — See plans