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.
For example,
Given nums = [1,3,-1,-3,5,3,6,7]
, and k = 3.
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
Therefore, return the max sliding window as [3,3,5,5,6,7]
.
Note:
You may assume k is always valid, ie: 1 ≤ k ≤ input array's size for non-empty array.
Follow up:
Could you solve it in linear time?
——————————————————————————————————————
naive solution 非常简单,两个指针,相隔k个,然后go over一遍找每个interval的最大值就好了。like this:
public class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums==null||nums.length==0)
return new int[0];
int[] max = new int[nums.length-k+1];
for(int i=0,j=k-1;j<nums.length;i++,j++){
int _max = -1000000;
for(int p=i;p<=j;p++){
if(nums[p]>_max)
_max = nums[p];
}
max[i] = _max;
}
return max;
}
}
然而,如果想做到O(n),还是要费一番心思的。
我目前想的是用deque,
例如1,3,-1,-3,5,第一组deque装的本该是【1,3,-1】,但是我们先算一下这个起始三个最大是3,然后把3装在deque的末端(deque的好处是两边都可以add或者remove),like this 【3,1,3,-1】,这样下一次三个应该是【3,-1,-3】,此时我们应该pop队尾的两个元素,3是表示最大值与下一值对比,如果比3比-3大,所以应该还在队尾,那么先赋给比如说叫temp吧然后把队尾倒数第二也就是sliding过去的1也给removeLast出去,然后再addLast把-3加回来,这是新元素比原max小的情况,大的情况也类似,就是依旧removeLast两个,然后addLast加上最新的元素就好了。
最棘手的是,下一回合最大值要被remove走,比如【3,-1,-3】,下一回合要remove的是一直以来的最大值3,这个时候只能再从三个数字中查一遍了。这样的话,最坏情况是,每过3个都要换一次最大值,于是必须“手动”对比3个数值,但是这次对比恰好抵消了最坏情况一下for(0 : n)每隔三步才要换一次max值,所以worst casehaishi.O(n). Best Case肯定是每隔三个恰好remove的同时是新的最大值,那么就是O(n/3) => O(n).