力扣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; } }

 

posted @ 2021-03-07 16:41  最近饭吃的很多  阅读(99)  评论(0编辑  收藏  举报