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:
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
- 题目要求的是求每个Sliding Window中的最大值,需要考虑用一种数据结构来记录当前窗口中,最大值及以后有可能成为最大值的数的
index
。 - 且该数据结构的
First Element
就是当前窗口的最大值,取的时候直接取第一个即可。同时,以后有可能成为最大值的存储在First Element
的后面。 所以可以用Deque
。
以上面例子为例,
- 扫描前面两个时,Sliding Window还不完整,没有最大值,所以此时只需要向
Deque
加入计算得到的最大值集合。 - 计算得到最大值集合的规则是:
- 如果
current value >= Last in Deque
,就remove Last
, 直到小于为止;然后将index of current
加入Deque
; (保持第一个永远是最大的) - 或者如果
current value < Last in Deque
, 也要将index of current
加入Deque
。因为其以后可能成为最大值。
---比如原始Deque
为[5]
,移动窗口后,新入的元素是3,需要把3加入Deque
,变成[5, 3]
,因为当5移出窗口后,3 有可能是最大值。
- 如果
- 从第三个数开始:
-- 首先用步骤2
得到最大值集合更新Deque
,然后取出First Element
,其就是当前窗口的最大值,加入结果集。
-- 再看即将被移动出窗口的那个数,是否是Deque
中第一个数,如果是就要将其从Deque
中移出。
class Solution {
Deque<Integer> deque = new ArrayDeque<>();
public int[] maxSlidingWindow(int[] nums, int k) {
// corner case
if (nums == null || nums.length < k || k == 0) {
return new int[0];
}
// init deque with [0, k - 1]
int[] result = new int[nums.length - k + 1];
for (int i = 0; i < k; ++ i) {
add(nums, i);
}
result[0] = nums[deque.peekFirst()];
for (int i = k; i < nums.length; ++ i) {
add(nums, i);
remove(nums, i - k);
result[i - k + 1] = nums[deque.peekFirst()];
}
return result;
}
private void add(int[] nums, int i) {
while (!deque.isEmpty() && nums[i] > nums[deque.peekLast()]) {
deque.pollLast();
}
deque.offerLast(i);
}
private void remove(int[] nums, int left) {
if (!deque.isEmpty() && deque.peekFirst() == left) {
deque.pollFirst();
}
}
}