Leetcode--Java--239. 滑动窗口最大值

题目描述

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

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

样例描述

Leetcode--Java--239. 滑动窗口最大值_第1张图片

思路

单调队列(用双端队列实现) O(nlogk)
核心思路:维护存储下标的单调队列,用下标范围来模拟滑动窗口

  1. 本题双端队列是左边头,右边尾,整体向右边移动。队列中存储的不是元素,而是下标,为了便于方便判断队首的元素是否还在窗口内
    Leetcode--Java--239. 滑动窗口最大值_第2张图片
  2. 对于每个右端点下标,判断其左端点是否还在窗口内,同时对于尾部新来的元素,判断是否大于队尾的元素,如果大于就不断删除队尾元素。(保证队列中是单调递减的性质,队首是最大值)。
  3. 可以预先设置结果数组,由于k个一组有个最大值,所以所有窗口最大值的个数为n - k + 1。
  4. 由右端点向前索引左端点。

代码

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
       int n = nums.length;
       Deque<Integer> dq = new LinkedList<>();
       int res[] = new int[n - k + 1];
       int cnt = 0;
       //枚举右端点,看左端点是否在窗口内
       for (int i = 0; i < n; i ++ ) {
           //队列不为空,并且左端点已经超过了队首,说明队首不在窗口内了,弹出队首
           if (!dq.isEmpty() && i - k + 1 > dq.peekFirst()) dq.removeFirst();
           //队列不为空,新来的元素大于队尾元素,删除所有小于队尾的,因为它们存在没意义
           while (!dq.isEmpty() && nums[i] > nums[dq.peekLast()]) dq.removeLast();
           //加入新来元素的下标
           dq.addLast(i);
           //如果长度大于k,才开始求max
           if (i >= k - 1) {
               res[cnt ++] = nums[dq.peekFirst()];
           }
       }
       return res;
    }
}

你可能感兴趣的:(Leetcode,单调队列,双端队列,下标模拟滑动窗口)