【单调队列】 239. 滑动窗口最大值

239. 滑动窗口最大值

解题思路

  • 计算每一个滑动窗口的最大值 关键在于借助单调队列实现窗口
  • 对于单调队列 尾部添加元素 头部删除元素
  • 添加元素操作:从尾部开始循环对比 删除比当前元素小的元素
  • 获取最大值元素 直接获取头部元素
  • 删除元素操作 直接删除头部元素
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
            // 借助单调队列  计算每一个滑动窗口的最大值
            MonotonicQueue window = new MonotonicQueue();// 单调队列窗口
            List<Integer> res = new ArrayList<>();


            for(int i = 0; i < nums.length; i++){
                if(i < k - 1){
                    window.push(nums[i]);// 先把前面k- 1 个元素填满
                }else{
                    // 窗口开始向前面移动
                    // 移入新的元素
                    window.push(nums[i]);

                    // 因为是单调队列  直接计算最大值
                    res.add(window.max());

                    // 移除最后的元素
                    window.pop(nums[i - k + 1]);
                }
            }

            // 将List 类型转换为int[] 数组 作为返回值
            int[] arr = new int[res.size()];

            for(int i = 0; i < res.size(); i++){
                arr[i] = res.get(i);
            }

            return arr;
    }

    // 单调队列的实现  尾部添加元素   头部删除元素  那么头部元素是最大值
    // 维护的单调队列 是需要从尾部到头部的元素 全部单调递增
    class MonotonicQueue{
        // 使用双链表 模拟队列  支持头部和尾部添加和删除元素
        private LinkedList<Integer> maxq = new LinkedList<>();

        public void push(int n){
            // 尾部添加一个元素  需要维护单调队列 从尾部到头部 单调递增的性质
            // 从尾部开始 将前面小于她的元素 全部删除掉  这样维护的就是一个单调队列
            while(!maxq.isEmpty() && maxq.getLast() < n){
                maxq.pollLast();// 删除尾部元素
            }
            maxq.addLast(n);// 添加元素   尾部添加元素
        }

        // 计算最大元素 直接就是取出 头部元素 因为头部元素最大
        public int max(){
            return maxq.getFirst();
        }

        // 头部删除元素
        public void pop(int n){
            if(n == maxq.getFirst()){
                maxq.pollFirst();
            }
        }
    }
}

你可能感兴趣的:(#,Leetcode,java,算法,数据结构)