给你一个整数数组
nums
,有一个大小为k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的k
个数字。滑动窗口每次只向右移动一位。返回 滑动窗口中的最大值 。
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 31 [3 -1 -3] 5 3 6 7 31 3 [-1 -3 5] 3 6 7 51 3 -1 [-3 5 3] 6 7 51 3 -1 -3 [5 3 6] 7 61 3 -1 -3 5 [3 6 7] 7
如果你刚看见这道题你会怎么想?三秒告诉我?3...2...1...,时间到!!!
首先是滑动窗口,一听到这个名字,我们就应该立刻的想到双指针,双指针这个大方向是错不了,我们再看,要每次取到范围内的最大值,除了最大堆就是优先队列可以做到这件事,接下来我们先用最大堆进行解题
最大堆就是其实就是一棵树,通过上浮和下浮使得堆顶是最大值或者最小值,Java中默认是最小堆,所以我们如果是想每次取到范围内的最大值,
PriorityQueue<Integer> queue=new PriorityQueue<>(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2-o1;//最大值 默认是o1-o2}});
需要对堆的比较器进行重写,构造一个最大堆
维护一个一个列表进行最大值的维护
List<Integer> list=new ArrayList<>();
for(int right=0;right< nums.length;right++){if(right<k-1){queue.offer(nums[right]);}else{queue.offer(nums[right]);list.add(queue.peek());queue.remove(nums[left++]);}}
结果,不出意外:
怎么办?时间超时了怎么办?堆的上浮和下沉确实浪费了大量的时间,所以我们使用另外一种数据结构解决本题(优先队列)
//维护一个单调队列class MaxQueue{private LinkedList<Integer> queue=new LinkedList<>();//添加public void push(int x){ //队列不为空,队尾元素如果小于当家加入元素,直接扔出去while(!queue.isEmpty()&&queue.getLast()<x){queue.pollLast();}queue.addLast(x);}//删除public void pop(int x){if(x==queue.getFirst()){queue.pollFirst();}}//得到最大值public Integer getMax(){return queue.getFirst();}}
核心代码:
int left=0;for(int right=0;right< nums.length;right++){if(right<k-1){window.push(nums[right]);}else{window.push(nums[right]);list.add(window.getMax());window.pop(nums[left++]);}}
结果,不出意外:
上源代码:
public int[] maxSlidingWindow(int[] nums, int k) {if(nums==null){return null;}MaxQueue window=new MaxQueue();List<Integer> list=new ArrayList<>();int left=0;for(int right=0;right< nums.length;right++){if(right<k-1){window.push(nums[right]);}else{window.push(nums[right]);list.add(window.getMax());window.pop(nums[left++]);}}return list.stream().mapToInt(Integer::valueOf).toArray();}//维护一个单调队列class MaxQueue{private LinkedList<Integer> queue=new LinkedList<>();//添加public void push(int x){while(!queue.isEmpty()&&queue.getLast()<x){queue.pollLast();}queue.addLast(x);}//删除public void pop(int x){if(x==queue.getFirst()){queue.pollFirst();}}//得到最大值public Integer getMax(){return queue.getFirst();}}