239 滑动窗口最大值

112 阅读1分钟

滑动窗口最大值

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

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

思路

1.暴力求解,超时!

2.实现一个单调队列,自己 diy 一种队列,与优先级队列不同,我们自己实现的单调队列的pop和push可以自定义。

实际上,只需要维护 可能 是最大值的数据。

基于双端队列 deque 来维护这个单调队列

单调队列

pop操作:也就是移除左端元素,想想什么时候pop。

举个例子:nums = [1,3,-1,-3,5,3,6,7], k = 3

当5准备入队时,最左端的3要被移除,因为元素3的下标是1,而元素5的下标是4,相差3,也就是k

push操作:队列中存的是下标,下标对应的值是从大到小排列的,每当要push一个元素时,从后往前删除不大于该元素的所有元素

getMaxValue操作:即队头元素

代码

 class Solution {
 public:
     vector<int> maxSlidingWindow(vector<int>& nums, int k) {
         vector<int> result;
         deque<int> dq;  // 起到单调队列的作用 下标不单调,但对应的值单调 大 -> 小
         // 保存可能成为最大值的元素
         // 存下标,而不是存值 原因:存下标可以帮助判断该元素什么时候被移出去
         int n = nums.size();
         for (int i = 0; i < n; i++)
         {
             // pop操作
             // 当队列非空且队头元素下标与当前要push进去的元素下标相差k时,pop
             if (dq.empty() != 1 && (i - dq.front() == k))
                 dq.pop_front();  // 左端最大值不能再用
 ​
             // push操作
             // 队列非空时,删除队列中不大于nums[i]的元素
             while (dq.empty() != 1 && nums[dq.back()] <= nums[i]) 
                 dq.pop_back();
             dq.push_back(i);
 ​
             // getMaxValue操作 
             if (i > k - 2)
                 result.push_back(nums[dq.front()]);
         }
         return result;
     }
 };