LeetCode239滑动窗口最大值(Java)

本文介绍了一种利用单调队列解决滑动窗口最大值问题的高效算法,并详细解释了其实现过程。通过构建初始窗口并确保队头始终为最大值,实现了在滑动窗口中快速查找最大值。
  • 如题:

    • 在这里插入图片描述
  • 思路:使用单调队列,即先构建初始窗口,大小为K,将前面K个元素依次加入队列中,加入的时候需要保证队头元素是最大的,由于队列先进先出,这样可以保证poll()弹出的元素是最大的。

    • 这样保证队列中队头元素最大:每次加入的时候和当前队尾元素比较(因此应该使用双端队列,可以操作队头和队尾),如果队列非空就拿队尾和当前元素比较,如果当前元素更大,就删除这个队尾元素,因为它不可能是最大值了然后直到找到大于等于当前元素的新队尾,将当前元素插入到这个元素之后具体细节在代码中注释标明!!
  • 解法如下:

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        // res数组记录每一轮窗口最大值,大小为K的窗口总共有num.lenth-k+1轮,
        // 即数组长度为num.lenth-k+1
        int[] res = new int[nums.length - k + 1];
        LinkedList<Integer> monotonicQueue = new LinkedList<>();
        for (int i = 0; i < k; i++) {//将前面k个元素形成窗口,之后就只需拿新加入的元素和窗口内的比较
            while (!monotonicQueue.isEmpty() && monotonicQueue.getLast() < nums[i]){
                /*如果队列非空就拿队列最后一个和当前元素比较,如果当前元素更大,就删除这个队尾元素,因为它不可能是最大值了。
                 但是注意:如果相同则不应该删除,因为每一轮 窗口右移 后都应该删除上一最左边的元素,
                 如果上一轮最左边的不是最大值,那么它就不会在队列里(上述规则说明了,在它后面的元素如果比他大会将它压出队列),
                 这种情况就不用删除。如果它是最大值,那么它就会在队头位置,所以我们窗口右移删除的时候只需要判断:
                 窗口最左边的元素 和 队列中的队头元素是否相等,如果相等则说明窗口最左边元素在队列中,
                 且是最大值,应该删除,否则该元素不在队列中,不用删除。
                 此时如果新加入的元素和它相等,那么如果你在刚刚比较的时候将<=新元素的都删除的话,
                 那么这个队头元素就在此时被删除,而之后我们将窗口右移的时候判断最左边元素与队头元素是否相等,
                 此时结果便是true,我们会将队头元素删除,但是这个队头元素实则是新加入的,造成误删!!!!*/
                monotonicQueue.pollLast();
            }
            monotonicQueue.add(nums[i]);
        }
        //从第k+1个位置即索引为k的位置和前面k个元素形成的窗口依次比较
        for (int i = k; i < nums.length; i++) {
            res[i-k] = monotonicQueue.peek();//每一轮比较前将上一轮最大的元素记录
            if(nums[i-k] == monotonicQueue.peek()){
                /*删除上一轮最左边的元素,因为窗口右移了
                 关键:这里只和队首元素比较,即最大元素,因为上一轮最左边的元素如果不是最大值,
                 则代表后面几位有比它更大的,而比它更大的元素在入队前会检查队尾元素是否比自己小,
                 如果比自己小则将这个元素删除,因为我们要返回的是最大值。
                 因此如果上一轮最左边的元素不是上一轮窗口的最大值,则肯定已经被移出了队列*/
                monotonicQueue.remove();//如果它是最大值则移出队列
            }
            while (!monotonicQueue.isEmpty() && monotonicQueue.getLast() < nums[i]){
                monotonicQueue.pollLast();
            }
            monotonicQueue.add(nums[i]);
        }
        res[nums.length - k] = monotonicQueue.peek();
        //之前循环到nums.length-1后就结束了,res中的最后一个元素位置是nums.length-k,而不是
        // nums.lenth - 1 - k,因此应该补上
        return res;
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一酒。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值