面试常考算法题(考察单调队列)--滑动窗口的最大值
Posted C_YCBX Py_YYDS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试常考算法题(考察单调队列)--滑动窗口的最大值相关的知识,希望对你有一定的参考价值。
题目
题目解析
这道题难的地方在于不能超时。。。O(n^2)必超时
为了防止重复比较,我们可以采取两个策略:
- 用优先队列构建最小堆。
- 用单调队列保存前几个最大值以防止重复比较。
这两种方法当然都存在一个问题=>需要判断当前的最大值是否存在于当前的窗口内,这个问题可以很简单的在这两种结构中得到解决,如果是优先队列我们只需要将下标和值同时保存,而如果是单调队列,那么我们可以保存下标即可。
第一时间想到用暴力法
看到这道题,很容易想到分割区间,每个操作区间为k长度,在每个区间内枚举它的最大值即可,然而时间复杂度是O(n^2)级别,到了第49个测试用例直接卡死。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int size = nums.size();
vector<int>res;
for(int i=0;size-i>=k;i++){
int m = *max_element(nums.begin()+i,nums.begin()+i+k);
res.push_back(m);
}
return res;
}
};
用单调队列
不断维护一个单调递减的队列,从最前面就可以取得它的最大值,为了判断是否在窗口内,这个入队的元素应该是下标,通过下标可以判断当前的最大值是否在当前窗口内,若不在当前窗口内,则出队一直到在窗口内。
class Solution {
public:
//维护一个从左到右单调递减的队列,并且队列中维护的是数组的下标(便于判断是否超出当前窗口)。
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int n = nums.size();
deque<int> Q;
vector<int>res;
//得到第一个窗口的结果
for(int i=0;i<k;i++){
//一旦出现不符合单调情况的,出队并将队列中的单调情况进行更新
while(!Q.empty()&&nums[i]>=nums[Q.back()]){
Q.pop_back();
}
Q.push_back(i);
}res.push_back(nums[Q.front()]);
//右移窗口不断更新数据,并判断是否最大值超出窗口
for(int i=k;i<n;i++){
while(!Q.empty()&&nums[i]>=nums[Q.back()]){
Q.pop_back();
}Q.push_back(i);
//得到不超过窗口的最大值
while(Q.front()<=i-k){
Q.pop_front();
}//更新窗口结果
res.push_back(nums[Q.front()]);
}
return res;
}
};
以上是关于面试常考算法题(考察单调队列)--滑动窗口的最大值的主要内容,如果未能解决你的问题,请参考以下文章