Sliding Window Maximum
Max of every length-k window via a monotonic deque.
3 min read
sliding-window monotonic-deque array
Problem#
Given nums and k, return an array of the maximum of every length-k window.
Examples#
nums = [1,3,-1,-3,5,3,6,7], k = 3→[3,3,5,5,6,7]nums = [1], k = 1→[1]
Constraints#
1 <= nums.length <= 10^5,1 <= k <= nums.length.
Hints#
Hint 1
Maintain indices of candidates in a deque, sorted by value descending. The front is always the current max.
Approach#
Monotonic deque storing indices. Before pushing i, pop indices with values ≤ nums[i] from the back (they’re dominated). Pop from the front if the index falls outside the window. The front is the answer for each window.
Solution#
class Solution {public: vector<int> maxSlidingWindow(vector<int>& nums, int k) { deque<int> dq; vector<int> ans; ans.reserve(nums.size() - k + 1); for (int i = 0; i < (int)nums.size(); ++i) { while (!dq.empty() && nums[dq.back()] <= nums[i]) dq.pop_back(); dq.push_back(i); if (dq.front() <= i - k) dq.pop_front(); if (i >= k - 1) ans.push_back(nums[dq.front()]); } return ans; }};func maxSlidingWindow(nums []int, k int) []int { dq := []int{} ans := make([]int, 0, len(nums)-k+1) for i := 0; i < len(nums); i++ { for len(dq) > 0 && nums[dq[len(dq)-1]] <= nums[i] { dq = dq[:len(dq)-1] } dq = append(dq, i) if dq[0] <= i-k { dq = dq[1:] } if i >= k-1 { ans = append(ans, nums[dq[0]]) } } return ans}from collections import dequefrom typing import List
class Solution: def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: dq: deque[int] = deque() ans: List[int] = [] for i, x in enumerate(nums): while dq and nums[dq[-1]] <= x: dq.pop() dq.append(i) if dq[0] <= i - k: dq.popleft() if i >= k - 1: ans.append(nums[dq[0]]) return ansfunction maxSlidingWindow(nums, k) { const dq = []; let head = 0; const ans = []; for (let i = 0; i < nums.length; i++) { while (dq.length > head && nums[dq[dq.length - 1]] <= nums[i]) dq.pop(); dq.push(i); if (dq[head] <= i - k) head++; if (i >= k - 1) ans.push(nums[dq[head]]); } return ans;}class Solution { public int[] maxSlidingWindow(int[] nums, int k) { int n = nums.length; int[] ans = new int[n - k + 1]; int idx = 0; Deque<Integer> dq = new ArrayDeque<>(); for (int i = 0; i < n; i++) { while (!dq.isEmpty() && nums[dq.peekLast()] <= nums[i]) dq.pollLast(); dq.offerLast(i); if (dq.peekFirst() <= i - k) dq.pollFirst(); if (i >= k - 1) ans[idx++] = nums[dq.peekFirst()]; } return ans; }}function maxSlidingWindow(nums: number[], k: number): number[] { const dq: number[] = []; let head = 0; const ans: number[] = []; for (let i = 0; i < nums.length; i++) { while (dq.length > head && nums[dq[dq.length - 1]] <= nums[i]) dq.pop(); dq.push(i); if (dq[head] <= i - k) head++; if (i >= k - 1) ans.push(nums[dq[head]]); } return ans;}Editorial#
Each index enters and leaves the deque exactly once → O(n). The deque encodes a monotonically decreasing sequence of candidates; smaller values that arrive after a larger value are useless once the larger value is still in the window (the larger one will be picked first). Front-stale check ensures the max actually lies within the current window.
Complexity#
- Time: O(n).
- Space: O(k).
Concept revision#
Related#