队列

EmiyaCC 于 2021-06-24 发布

单调队列

类似单调栈,就是一个「队列」,只是使用了一点巧妙的方法,使得队列中的元素全都是单调递增(或递减)的。可以解决滑动窗口相关的问题。

滑动窗口最大值

对于滑动窗口,最主要是是记录窗口内的最大值。假设有 i 和 j 下标(i < j),对应 nums[i] 和 nums[j](nums[i] <= nums[j]),那么 i 下标对应的值肯定是比 j 下标对应的值先出窗口,也就是说 i 和 j 存在的场合,i 对应的值 nums[i] 其实是不需要记录的,因为最大值肯定是 nums[j]

由于滑动窗口以下标操作位置,所以建议 Stack 记录下标(单调栈中,下一个更大值1 主要是对值操作,所以记录值,下一个更大值2每日温度,主要是对下标操作,所以记录下标)

本题需要对比队列前面的值和后面的值,所以需要用到 Deque

// https://leetcode-cn.com/problems/sliding-window-maximum/
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        Deque<Integer> deque = new LinkedList<>();
        int len = nums.length;
        for (int i = 0; i < k; i ++) {
            while (!deque.isEmpty() && nums[deque.peekLast()] <= nums[i]) {
                deque.pollLast();
            }
            deque.offerLast(i);
        }
        int[] res = new int[len - k + 1];
        res[0] = nums[deque.peekFirst()];
        for (int i = k; i < len; i ++) {
            while (!deque.isEmpty() && nums[deque.peekLast()] <= nums[i]) {
                deque.pollLast();
            }
            deque.offerLast(i);
            // 如果 deque 中的下标划出窗口了
            while (deque.peekFirst() <= i - k) {
                deque.pollFirst();
            }
            res[i - k + 1] = nums[deque.peekFirst()];
        }
        return res;
    }
}

Reference:

  • https://labuladong.gitee.io/algo/
  • https://leetcode-cn.com/problems/