Leetcode 239. 滑动窗口最大值 (Java实现 超详细注释!)

Leetcode 239. 滑动窗口最大值

涉及双向队列,说实话有点难理解啊!加了详细的注释,方便日后复习,也希望能帮到其他小伙伴,如有错误,欢迎指正!

Java实现:

class Solution {
     
    public int[] maxSlidingWindow(int[] nums, int k) {
     
        int n = nums.length;
        // 由于滑动窗口本质就是每次删除最前面的一个元素,添加一个元素再后面,因此这里我们用双向队列存储滑动窗口内的元素,方便增删
        Deque<Integer> dq = new LinkedList<Integer>();
        // res用来存储每次滑动窗口内的最大值
        int[] res = new int[n - k + 1];
        // 移动滑动窗口,其实就是从前往后移动,每一移动一位
        for (int i = 0; i < n; i++){
     
            // 由于我们需要找到滑动窗口内的最大值,我们可以采取这样的方法:
            // 我们让队列头部放最大值的索引(用索引是因为后面需要判断是否要删除已经越界的元素),队列的尾部存较小且靠后的元素
            /**我们怎么才能做到上述呢?
            头部放最大的元素就是每次移动窗口时都从后往前比较新元素和老元素的大小,只要新元素更大就不断地替换老元素,直到已经没有老元素了
            怎么保证队列的尾部存较小且靠后的元素?我们可以在新元素小于最后一个老元素时,将新元素放在队列的尾部;
            */
            while (!dq.isEmpty() && nums[dq.getLast()] <= nums[i]){
     
                dq.pollLast();
            }
            dq.offerLast(i);

            /**此时这次的窗口滑动已经结束了,我们要考虑是否有上一次的老元素越界的情况,因为是按顺序存储的,第一个元素一定是最靠前的元素;
            因此只有可能该元素越界,我们判断该元素的索引是否等于i - k,等于说明越界,直接删除*/
            if (dq.peekFirst() == i - k){
     
                dq.pollFirst();
            }
            // 到这一步我们需要获取窗口内的最大值了,由于不满三个元素时,不需要求最大值,从遍历到第k个元素开始才需要求最大值
            if (i >= k - 1){
     
                // 由于最大的会一直往前挪,队列头部的元素此时一定是窗口内的元素,直接存入res中即可
                res[i - k + 1] = nums[dq.peekFirst()];
            }
        }
        return res;
    }
}

你可能感兴趣的:(Leetcode,队列)