0
点赞
收藏
分享

微信扫一扫

LeetCode239滑动窗口最大值(Java)

耶也夜 2022-03-26 阅读 85
  • 如题:

    • 在这里插入图片描述
  • 思路:使用单调队列,即先构建初始窗口,大小为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;
    }
}
举报

相关推荐

0 条评论