Sliding Window Maximum
Question
Given an array of n integer with duplicate number, and a moving window(size k), move the window at each iteration from the start of the array, find the maximum number inside the window at each moving.
Example
For array [1, 2, 7, 7, 8], moving window size k = 3. return [7, 7, 8]
At first the window is at the start of the array like this
[|1, 2, 7| ,7, 8] , return the maximum 7;
then the window move one step forward.
[1, |2, 7 ,7|, 8], return the maximum 7;
then the window move one step forward again.
[1, 2, |7, 7, 8|], return the maximum 8;
Example 2
Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3
Output: [3,3,5,5,6,7]
Explanation:
Window position Max
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7Note: You may assume _k _is always valid, 1 ≤ k ≤ input array's size for non-empty array.
Challenge
o(n) time and O(k) memory
Tags
LintCode Copyright Deque Zenefits
Related Problems
Hard Sliding Window Matrix Maximum 35 % Hard Paint House II 28 % Hard Sliding Window Median
Analysis
Deque
开始想到用一个固定大小的Max Heap,但是由于Heap的删除操作比较麻烦,最好使用HashHeap,不过HashHeap在Java中并没有现成的implementation,而其实现十分繁琐,因此转而思考有没有别的数据结构。相比Sliding Window Median,这里寻找Maximum也许更容易一些,因为是一个局部极值,也许可以用stack或者queue来记录当前窗口的最大元素?但是单纯使用stack或者queue都不能很好地满足需要,因为想维护一个数据结构,能够保持其元素的单调递减性,其头部永远是当前window的maximum,如果有新的较大元素,则将该结构内比它小的元素都pop出来,再push新的较大元素。Java中恰好有这样一个数据结构:Deque,也就是double-ended-queue,“双端队列”之意,其中一个实现为ArrayDeque (参考:https://docs.oracle.com/javase/7/docs/api/java/util/ArrayDeque.html),能够满足两端的offer, poll, peek操作。也可以直接用LinkedList实现。
对于example:
先将k-1个元素填入,
从kth元素开始,再依次加入新元素并且删除原有旧元素,保持sliding window的大小不变
对于每一个nums中的元素都只扫描一遍,在deque中的操作时间复杂度也是在O(k)数量级以下,因此总时间复杂度为O(n * k) ~ O(n),空闲复杂度O(k),用于维护一个Deque。
We scan the array from 0 to n-1, keep "promising" elements in the deque. The algorithm is amortized O(n) as each element is put and polled once.
At each i, we keep "promising" elements, which are potentially max number in window [i-(k-1),i] or any subsequent window. This means
If an element in the deque and it is out of i-(k-1), we discard them. We just need to poll from the head, as we are using a deque and elements are ordered as the sequence in the array
Now only those elements within [i-(k-1),i] are in the deque. We then discard elements smaller than a[i] from the tail. This is because if a[x] <a[i] and x<i, then a[x] has no chance to be the "max" in [i-(k-1),i], or any other subsequent window: a[i] would always be a better candidate.
As a result elements in the deque are ordered in both sequence in array and their value. At each step the head of the deque is the max element in [i-(k-1),i]
记录max index
每次循环在sliding window里找到maximum对应的index,在下一次循环中根据新加入window的元素大小以及更新这个index,可以达到O(1) space, O(n) time的算法。
Monotonic Queue
也有大神解读为monotonic queue problem https://leetcode.com/problems/sliding-window-maximum/discuss/65885/This-is-a-typical-monotonic-queue-problem
Solution
Deque - Storing Value in Deque
*Deque - Storing Index in Deque - Monotonic Queue (17ms 51.07% AC)
The dq head always stores the index of maximum in the sliding window
Alternative Approach 1 - Time O(n) Space O(1) (1ms AC)
max_index - the index of maximum in current (or previous if in next loop) sliding window
Alternative Approach 2 - Two max arrays - Time O(n) Space O(n) - (4ms AC)
Reference
[GeeksforGeeks: Sliding Window Maximum](https://www.geeksforgeeks.org/sliding-window-maximum-maximum-of-all-subarrays-of-size-k/\
Last updated
Was this helpful?