【算法笔记】滑动窗口最大值

滑动窗口最大值问题

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。


问题分析

可使用单调队列解决问题(java中使用LinkedList来实现单调队列),队列从头到尾是从大到小的,那么队头元素就是需要返回的最大值,只需每次让队头弹出就行。当滑动窗口移动时,我们需要弹出在窗口外的元素,因为是按大小顺序入的队,所以队首元素不一定是需要弹出的元素,如何解决呢?

其实没有必要将所有元素都入队,只需要保证队列元素是从大到小的,并且保证可能成为最大值的元素都入队。
具体操作

  • 入队时,判断队尾元素是否小于该元素,是则弹出队尾元素,直到否时将该元素入队。
  • 滑动窗口滑动时移除元素的操作,因为滑动窗口的范围为[i-k+1,i],所以当队首元素小于等于nums[i-k]时,表示当前队首元素在滑动窗口外,需要移除。

代码

public int[] maxSlidingWindow(int[] nums, int k) {

    //如果数组为空,或者小于2直接返回
    if(nums == null || nums.length < 2) {
        return nums;
    }

    // 单调队列,从大到小保存当前窗口中的值,不一定是全部值,是可能成为滑动窗口最大值的元素
    LinkedList<Integer> queue = new LinkedList();

    // 保存结果数组
    int[] result = new int[nums.length-k+1];

    // 遍历nums数组,实现滑动窗口的操作
    for(int i = 0;i < nums.length;i++){

        // 保证队列里的元素从大到小 如果队尾元素小于当前待入队元素,则需要依次弹出,直至满足要求
        while(!queue.isEmpty() && queue.peekLast() < nums[i]){
            queue.pollLast();
        }

        //将元素加入队列
        queue.addLast(nums[i]);

        // 判断当前队列中队首元素是否为滑动后需要移除的元素,滑动窗口的范围为[i-k+1,i]
        if(i+1 > k && queue.peek() <= nums[i-k]){
            queue.poll();
        }

        //保存窗口中最大值
        if(i+1 >= k){
            result[i+1-k] = queue.peek();
        }
    }
    return result;
}

你可能感兴趣的:(算法,队列,算法,java,数据结构,leetcode)