Problem description:

Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
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] 7

Note:
You may assume k is always valid, 1 ≤ k ≤ input array’s size for non-empty array.

Follow up:
Could you solve it in linear time?

Solution:

The basic idea is to use a deque (buffer) to save all currently potential “maximum” elements (i.e. the element in the current k-element window [i-k+1, i], and it is larger than the elements after itself).

So for each i, we first pop up the elements that are no larger than nums[i] from buffer until we find one that is larger than nums[i] or the buffer is empty since those elements will be covered by nums[i] and can not be a maximum of any k-element window.

Then we put nums[i] in the buffer. If i>=k-1, we need to ouput the maximum for window [i-k+1, i], which is the front element of buffer. At last, we will check if the front element is nums[i-k+1], if so, we have to pop it up since it will be out of the window [i-k+2, i+1] in the next iteration. Since all the elements will be pushed into/ popped out of the buffer only once, so the time complexity is O(N).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
q = deque()
res = []
for i, n in enumerate(nums):
# keep pop out element if new element is greater
while q and nums[q[-1]] < n:
q.pop()
q.append(i)

# if the first element out of window
if q[0] == i - k:
q.popleft()
if i >= k-1:
res.append(nums[q[0]])
return res
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> deq;
vector<int> res;

for(int i= 0; i< nums.size(); i++){
while(!deq.empty() && nums[i] >= nums[deq.back()]) {
//printf("pop out: nums[%d]=%d\n", deq.back(), nums[deq.back()]);
deq.pop_back();
}

deq.push_back(i);

if(i >= k-1) res.push_back(nums[deq.front()]);
if(deq.front() <= i-k+1) deq.pop_front();
}
return res;
}
};

time complexity: $O(n)$
space complexity: $O(k)$
reference:
https://goo.gl/mvk9ht