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.
Follow up:
Could you solve it in linear time?
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
Constraints:
1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
1 <= k <= nums.length
给出一个数组和size为k的滑动窗口,每次滑动窗口向右移动一位,输出每次移动中滑动窗口中的最大值。
假设数组长度为n,那么一共输出n-k+1个窗口最大值。
思路:
最简单粗暴的方法是每移动一位就在滑动窗口内搜索最大值。
此处参考一个方法,用一个单调储存元素的队列,最大值在队列的head,而且每次添加元素时把小于新元素的全部删掉,那么每次输出仅需要输出队列的head元素。
注意队列中可以储存重复的元素,因为假如窗口右移时左边元素出了窗口,就需要把左边的元素移除队列,这时如果左边元素是最大值,相当于最大值移除队列,但是如果窗口中仍有同样的最大值元素,就应该有重复的元素仍然在队列中。
java中用到deque结构,用到ArrayDeque, 其中getFirst和offerFirst的区别是如果队列中没有元素,那么getFirst会抛出Exception, 但是offerFirst不会抛出异常,会直接返回null, 同样的还有pollFirst(不抛出异常)和removeFirst(会抛出异常)。
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
monoQueue queue = new monoQueue();
int n = nums.length;
int[] result = new int[n - k + 1];
for(int i = 0; i < nums.length; i++) {
queue.push(nums[i]);
if(i >= k && nums[i - k] == queue.getMax()) {
queue.pop();
}
if(i + 1 >= k) {
result[i - k + 1] = queue.getMax();
}
}
return result;
}
}
class monoQueue{
private Deque<Integer> deque = new ArrayDeque<>();
//add element and delete all elements smaller than it
public void push(int num) {
while(!deque.isEmpty() && num > deque.peekLast()) {
deque.pollLast();
}
deque.offerLast(num);
}
//delete the head(max element)
public void pop(){
deque.pollFirst();
}
//return the head(max element)
public int getMax(){
return deque.peekFirst();
}
}