力扣239题(单调队列)
239、滑动窗口最大值
基本思想:
需要实现一个队列,这个队列中放入窗口里的元素,
随着窗口的移动,队列也一进一出,
每次移动之后,队列头显示里面的最大值
具体实现:
1.单调队列(递增或递减)
队列中列表中的元素永远是单调递减的,第一个值永远是最大的,
进来一个比第一个值还大的值以后
就把新进来的这个值前面的值都踢出去
队列永远是单调递减的
2.队列没有必要维护窗口里的所有元素,
只需要维护有可能成为窗口里最大值的元素就可以了,
同时保证队里里的元素数值是由大到小的。
代码:
class MyQueue { Deque<Integer> deque = new LinkedList<>(); //弹出元素时,比较当前要弹出的数值是否等于队列头的数值,如果相等则弹出 //同时判断队列当前是否为空 void poll(int val) { if (!deque.isEmpty() && val == deque.peek()) { deque.poll(); } } //添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出 //保证队列元素单调递减 //比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2 void add(int val) { while (!deque.isEmpty() && val > deque.getLast()) { deque.removeLast(); } deque.add(val); } //队列队顶元素始终为最大值 int peek() { return deque.peek(); } } class Solution { public int[] maxSlidingWindow(int[] nums, int k) { if (nums.length == 1) { return nums; } int len = nums.length - k + 1; //存放结果元素的数组 int[] res = new int[len]; int num = 0; //自定义队列 MyQueue myQueue = new MyQueue(); //先将前k的元素放入队列 for (int i = 0; i < k; i++) { myQueue.add(nums[i]); } res[num++] = myQueue.peek(); for (int i = k; i < nums.length; i++) { //这里移除最前面的元素的前提是因为队列中窗口满了,这里需要判断窗口的第一个元素是否还在队列中,
//不在的话,说明它在单调队列的时候已经被弹出了,
myQueue.poll(nums[i - k]); //滑动窗口加入最后面的元素 myQueue.add(nums[i]); //记录对应的最大值 res[num++] = myQueue.peek(); } return res; } }