首页 剑指 Offer 59 - I. 滑动窗口的最大值
文章
取消

剑指 Offer 59 - I. 滑动窗口的最大值

题目描述

给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7] 
解释: 

  滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

提示:

你可以假设 k 总是有效的,在输入数组 不为空 的情况下,1 ≤ k ≤ nums.length

解题

单调队列:

  • 利用 deque 维护一个单调递减队列
  • 队首为当前窗口的最大值
  • push 时,保证插入的元素小于队尾元素(若大于,则循环弹出队尾元素)
  • pop 时,如果 pop 的元素值时队首元素则弹出,否则不做任何处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Solution {
private:
    deque<int> dq;
    
    void dq_push(int val){
        // 维护单调栈
        while ( !dq.empty() && val > dq.back() ) {  // 这里不能等于,因为数组中可能有重复
            dq.pop_back();
        }
        dq.push_back(val);
    }

    void dq_pop(int val){
        // 只有在 val 和单调栈首相等时才弹出
        if ( !dq.empty() && val == dq.front() ) {
            dq.pop_front();
        }
    }

    int dq_max(){
        if( !dq.empty() ) return dq.front();
        else return -1;
    }
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        // 先初始化 窗口大小为 k 的单调栈
        for ( int i = 0; i < k; i++ ) {
            dq_push(nums[i]);
        }
        vector<int> res;
        res.push_back(dq_max());
        for ( int i = k; i < nums.size(); i++ ) {
            dq_pop(nums[i - k]);
            dq_push(nums[i]);
            res.push_back(dq_max());
        }

        return res;
    }
};

复杂度分析:

  • 时间复杂度 O(N) : 遍历数组使用 O(N) 时间。

  • 空间复杂度 O(1) : 常数量变量为 O(1)

写在最后

感谢你在茫茫人海中找到我🕵🏼

🎉你是第 个读者

㊗️ 你平安喜乐,顺遂无忧!

希望你读完有所收获~

🥂🥂🥂

本文由作者按照 CC BY 4.0 进行授权

剑指 Offer 63. 股票的最大利润

剑指 Offer 26. 树的子结构