leetcode 239. 滑动窗口最大值

@(labuladong的算法小抄)[单调队列]

leetcode 239. 滑动窗口最大值

题目描述

在这里插入图片描述
在这里插入图片描述

解题思路

参考:labuladong的算法小抄P271

在一堆数字中,已知最值为A,如果给这堆数添加一个数B,那么比较一下A和B就可以立即算出新的最值;但如果减少一个数,就不能直接得到最值了,因为如果减少的这个数恰好是A,就需要遍历所有数重新找出新的最值。

因此,由于窗口每次前进的时候,要添加一个数同时减少一个数,所以想得到新的最值不容易。

本题采用单调队列的方法解决。

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        /* 单调队列,队列中的元素从队头到队尾保持递减 */
        MonotonicQueue window = new MonotonicQueue();
        int[] res = new int[nums.length - k + 1];

        for (int i = 0; i < nums.length; i++) {
            /* 先填满窗口的前k-1 */
            if (i < k - 1) {
                window.push(nums[i]);
            } else {
                /* 窗口开始滑动 */
                /* 移入新元素 */
                window.push(nums[i]);
                /* 将当前窗口中的最大值记入结果 */
                res[i - k + 1] = window.getMax();
                /* 移出窗口最前面的元素 */
                window.pop(nums[i - k + 1]);
            }
        }
        return res;
    }

    private class MonotonicQueue {
        /* 双向链表,支持头部和尾部增删元素,复杂度为o(1) */
        LinkedList<Integer> q = new LinkedList<>();
        /* 在队尾将n入队 */
        private void push(int n) {
            /* 将两个高个儿元素之间的元素全部出队 */
            while (!q.isEmpty() && q.getLast() < n) {
                q.removeLast();
            }
            q.addLast(n);
        }
        /* 返回队列中的最大值 */
        private int getMax() {
            /* 队列中的元素从队头到队尾保持递减,因此最大值就是队头元素 */
            return q.getFirst();
        }
        /* 在队头删除元素n */
        private void pop(int n) {
            /* 如果队头元素正好是要删的元素,则删除;否则,说明要删的元素在之前已经被当成矮个儿出队了,不用管 */
            if (q.getFirst() == n) {
                q.removeFirst();
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值