239. 滑动窗口最大值

85 阅读2分钟

Problem: 239. 滑动窗口最大值

@[TOC]

思路

这个问题可以使用一个数据结构叫做单调队列来解决。单调队列是一种特殊的队列,它可以在 O(1) 的时间复杂度内获取队列中的最大值(或最小值)。在这个问题中,我们可以从左到右遍历数组,将每个数字加入到单调队列中。同时,我们需要保持单调队列的第一个元素始终是当前窗口的最大值。

解题方法

我们首先初始化一个空的单调队列和一个结果数组。然后,我们从左到右遍历输入数组,对于每个元素,我们首先从单调队列的尾部开始,移除所有小于当前元素的元素,然后将当前元素加入到单调队列的尾部。这样,我们可以确保单调队列的第一个元素始终是当前窗口的最大值。 然后,我们需要检查单调队列的第一个元素是否在当前窗口的范围内,如果不在,我们就将其从单调队列中移除。最后,我们将单调队列的第一个元素加入到结果数组中。

复杂度

时间复杂度:

O(n)O(n),其中n是数组的长度。每个元素只会被加入到单调队列一次,所以时间复杂度是线性的。

空间复杂度:

O(n)O(n),在最坏的情况下,单调队列中可能会包含所有的元素,所以空间复杂度是线性的。

Code

class Solution {
    public static int MAXN = 100001;
    public static int[] deque = new int[MAXN];
    public static int h, t;

    public static int[] maxSlidingWindow(int[] nums, int k) {
        h = t = 0;
        int n = nums.length;
        // 首先形成k - 1的窗口
        for (int i = 0; i < k - 1; i++) {
            while (h < t && nums[deque[t - 1]] <= nums[i]) {
                t--;
            }
            deque[t++] = i;
        }
        int m = n - k + 1;
        int[] ans = new int[m];

        for (int l = 0, r = k - 1; l < m; l++, r++) {
            while (h < t && nums[deque[t - 1]] <= nums[r]) {
                t--;
            }
            deque[t++] = r;
            ans[l] = nums[deque[h]];
            if (deque[h] == l) {
                h++;
            }
        }
        return ans;
    }
}