单调队列,即单调递减或单调递增的队列。
单调队列的作用:用来解决“滑动窗口”问题。
1438. 绝对差不超过限制的最长连续子数组
239. 滑动窗口最大值
题中说满足任意两个数的差值的绝对值<=limit,那么只需要让这个数组中的最大值与最小值的差值<=limit即可,关键就是如何寻找一个数组内的最大值与最小值,同时数组一直在改变。并且当最大值与最小值的差值>limit时,我们要按照给出的数字的顺序将最小值或者最大值pop掉,直到满足<=limit,更新元素的个数。
代码:
class Solution {
public:
int longestSubarray(vector<int>& nums, int limit) {
int n=nums.size();
int left=0,right=0,ans=0;
deque<int>quen,quex;
while(right<n)
{
while(!quex.empty()&&nums[right]>quex.back())
quex.pop_back();
while(!quen.empty()&&nums[right]<quen.back())
quen.pop_back();
quex.push_back(nums[right]);
quen.push_back(nums[right]);
right++;
while(quex.front()-quen.front()>limit)
{
if(quex.front()==nums[left]) quex.pop_front(); //最大值
if(quen.front()==nums[left]) quen.pop_front(); //最小值
left++;
}
ans=max(ans,right-left);
}
return ans;
}
};
思路与上一题大致相同,只不过该题需要求出有几个子数组满足当前条件,例如:当数组为[4,2]s时,添加一个4,数组会有[4,2,4],[2,4],[4]种情况,对应添加了i-left+1个数组。一般对两者之差有限制的话,都两个队列,一个为存放最大值的队列,一个为存放最小值的队列。
代码:
class Solution {
public:
long long continuousSubarrays(vector<int>& nums) {
int n=nums.size();
long long ans=0;
int left=0,right=0;
deque<int>quex,quen;
while(right<n)
{
while(!quex.empty()&&nums[right]>quex.back())
quex.pop_back();
while(!quen.empty()&&nums[right]<quen.back())
quen.pop_back();
quex.push_back(nums[right]);
quen.push_back(nums[right]);
while(quex.front()-quen.front()>2)
{
if(nums[left]==quex.front()) quex.pop_front();
if(nums[left]==quen.front()) quen.pop_front();
left++;
}
ans+=right-left+1;
right++;
}
return ans;
}
};
先插入k个元素,其中que.front()永远为这个窗口中元素的最大值,那么如何push元素与如何pop元素成为关键,因为que.front()为最大元素值,那么要插入的这个值比队列中的值大的话,那么把队列中小的给pop掉,使得队首为长度为k的元素中的最大值,最后答案为每次操作后队列的队首。
代码:
class Solution {
private:
class MyQueue {
public:
deque<int>que;
void pop(int val)
{
if(!que.empty()&&val==que.front())
que.pop_front();
}
void push(int val)
{
while(!que.empty()&&val>que.back())
que.pop_back();
que.push_back(val);
}
int front()
{
return que.front();
}
};
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
MyQueue que;
vector<int>ans;
int n=nums.size();
for(int i=0;i<k;i++)
{
que.push(nums[i]);
}
ans.push_back(que.front());
for(int i=k;i<n;i++)
{
que.pop(nums[i-k]);
que.push(nums[i]);
ans.push_back(que.front());
}
return ans;
}
};
代码:
#include<bits/stdc++.h>
using namespace std;
int a[1000009];
int n;
void quemax(int a[],int k)
{
deque<int>que;
vector<int>ans;
for(int i=0;i<k;i++)
{
while(!que.empty()&&a[i]>que.back())
que.pop_back();
que.push_back(a[i]);
}
ans.push_back(que.front());
for(int i=k;i<n;i++)
{
if(!que.empty()&&a[i-k]==que.front())
que.pop_front();
while(!que.empty()&&a[i]>que.back())
que.pop_back();
que.push_back(a[i]);
ans.push_back(que.front());
}
for(int i=0;i<ans.size()-1;i++)
{
cout<<ans[i]<<' ';
}
cout<<ans[ans.size()-1]<<endl;
}
void quemin(int a[],int k)
{
deque<int>que;
vector<int>ans;
for(int i=0;i<k;i++)
{
while(!que.empty()&&a[i]<que.back())
que.pop_back();
que.push_back(a[i]);
}
ans.push_back(que.front());
for(int i=k;i<n;i++)
{
if(!que.empty()&&a[i-k]==que.front())
que.pop_front();
while(!que.empty()&&a[i]<que.back())
que.pop_back();
que.push_back(a[i]);
ans.push_back(que.front());
}
for(int i=0;i<ans.size()-1;i++)
{
cout<<ans[i]<<' ';
}
cout<<ans[ans.size()-1]<<endl;
}
int main()
{
int k;
cin>>n>>k;
for(int i=0;i<n;i++)
{
cin>>a[i];
}
quemin(a,k);
quemax(a,k);
return 0;
}