先上题目
这道题是一道入门级别的滑动窗口+单调队列题目。
如题所示我们只需要维护一个固定大小的窗口,然后找到其中的最大值。暴力方法来做的话就是枚举每一个窗口中的最大值,对于每个窗口线性扫描一遍的时间复杂度是O(k),整体的时间复杂度就是O(n*k),对于该题10^10的复杂度就会超时。
用单调队列来做的话,我们只需要每次取出队头元素即可,即时间复杂度是O(1),每个元素最多push一次,pop一次,所以整体的时间复杂度是O(n)。
整体可以分为以下四步:
1.解决队首已经出窗口的问题;
2.解决队尾与当前元素a[i]不满足单调性的问题;
3.将当前元素下标加入队尾;
4.如果满足条件则将将队头push进数组中。
对于单调队列来说,如果现在要入队的元素比队尾大的话,那么队尾可以直接出队(用数组来模拟队列的话类似于双端队列),因为队尾必定要比将要进入队列的元素先出队列,所以最大值也轮不到目前的队尾元素。
代码及注释如下:
class Solution {
public:
int q[100010]; //用数组模拟队列,用来存储下标
int hh=0,tt=-1;//hh代表队头,tt代表队尾
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> res;//用于返回的数组。
int n=nums.size();
for(int i=0;i<n;++i){
if(i-k+1>q[hh]) hh++;//如果队列的长度大于k,则队头出队
while(hh<=tt&&nums[i]>=nums[q[tt]]) tt--;//保证单调性,使得队头元素一定是最大的,不会出现队头元素大于下一个元素的情况。
q[++tt]=i;//i入队列
if(i-k+1>=0) res.push_back(nums[q[hh]]);//窗口的大小要达到k才能开始往数组里push
}
return res;
}
};
作者:uhspn
链接:https://leetcode.cn/problems/sliding-window-maximum/solution/by-uhspn-lqmd/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。