【双端队列】【维护单调队列】Leetcode 239 滑动窗口最大值【难】

【双端队列】Leetcode 239 滑动窗口最大值

    • 双端队列的操作
    • 解法1 利用双端队列实现单调队列

---------------题目链接 Leetcode 239 滑动窗口最大值-------------------

【双端队列】【维护单调队列】Leetcode 239 滑动窗口最大值【难】_第1张图片

双端队列的操作

创建双端队列:Deque mydeque = new Deque<>()
双端队列的队首元素:mydeque.peekFirst()
双端队列的队尾元素:mydeque.peekLast()
双端队列的队首元素弹出:mydeque.pollFirst()
双端队列的队尾元素弹出:mydeque.pollLast()
双端队列的队首元素加入:mydeque.addFirst()
双端队列的队尾元素加入:mydeque.addLast()

解法1 利用双端队列实现单调队列

首先,先从第一个滑动窗口开始维护一个单调队列:这里向队列内添加元素时,需要始终保证mydeque.peekLast() 大于 新添加的元素,即如果新添加的元素大于队列末尾的元素时,需要while弹出队列末尾元素(直到满足上述条件),之后再将新元素添加到队列末尾:mydeque.addLast(新元素)
其次,在窗口开始滑动的时候,每次滑动后,需要验证当前队列中队首元素(也就是目前队列中的最大元素)是否是在滑动中需要被踢出队列的元素(比如当前队列中的-3 1 3 再次进行滑动后 ——按照原数组位置来看3会被踢出):即判断mydeque.peekFirst() 是否等于 nums[i-k],若等于,则踢出队首元素后再进行第一步中的入队验证等一系列操作。
最后,从遍历的i>k-1开始,每次都要输出result[i-k+1] = mydeque.peekFirst() 即输出滑动窗口内的最大值至result数组。

时间复杂度O(N):使用单调队列的时间复杂度是 O(n)
空间复杂度O(K) :K就是自己维护的队列的长度

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        Deque<Integer> mydeque = new LinkedList<>();
        int[] result = new int[nums.length-k+1];

        int index = 0;
        for(int i = 0; i<nums.length; i++){
            // 弹出队列操作: 如果当前队列首部元素是滑动窗口即将划走的元素 那么就从双端队列的头部弹出他
            if(i > k-1 && mydeque.peekFirst() == nums[i-k]){
                mydeque.pollFirst();
            }

            // 保证添加到队列中的元素 队头(大)>>> 队尾(小)
            // 如果当前队列尾部元素小于nums[i] 就循环弹出队尾元素
            while(!mydeque.isEmpty() && mydeque.peekLast()<nums[i]){
                mydeque.pollLast();
            }
            mydeque.addLast(nums[i]);

            
            //得到队首值mydeque.peekFirst() 即为最大值
            if(i >= k-1){
                result[i-k+1] = mydeque.peekFirst();
            }
            
        }
        return result;
    }
}        
    

你可能感兴趣的:(Leetcode,leetcode,算法,数据结构,java,职场和发展)