赞
踩
使用单调队列解题,队列里存储的是下标。我是看https://www.bilibili.com/video/BV1H5411j7o6我是看这个视频想清楚单调队列是怎么用的,写这个文章来保存一下我的思路和解题过程
利用递减队列找窗口最大值,队头保存的是最大值
利用递增队列找窗口最小值,队头保存的是最小值
#include <iostream> #include <queue> #include <vector> using namespace std; int main() { int n,k; vector<int> v,ansBig,ansLittle; deque<int> q; //双向队列 //输入n、k和序列a cin>>n>>k; while(n--){ int t; cin>>t; v.push_back(t); } //找大的,此为递减队列 for(int i=0;i<v.size();i++){ //这里是为了使窗口滑过去后,不在这个窗口范围里的最大值弹出队列 if(!q.empty() && i-q.front()>=k) q.pop_front(); //正常的单调队列过程 if(q.empty() || v[q.back()]>v[i]){ q.push_back(i); } else{ while(!q.empty() && v[q.back()]<=v[i]){ q.pop_back(); } q.push_back(i); } //因为队列是从序列a的第1个数开始入栈的,而窗口一开始是从框着前k个数开始的,所以 //要到前k个数都经历过一遍这个单调队列过程后,在把队头的最大值放入最大值答案数组里 if(i>k){ ansBig.push_back(v[q.front()]); } } //找小的,此为递增队列 q.clear(); //清空队列 for(int i=0;i<v.size();i++){ //这里是为了使窗口滑过去后,不在这个窗口范围里的最小值弹出队列 if(!q.empty() && i-q.front()>=k) q.pop_front(); //正常的单调队列过程 if(q.empty() || v[q.back()]<=v[i]){ q.push_back(i); } else{ while(!q.empty() && v[q.back()]>v[i]){ q.pop_back(); } q.push_back(i); } //同理 if(i>k){ ansLittle.push_back(v[q.front()]); } } //输出窗口里最小的数 for(int i=0;i<ansLittle.size();i++){ cout<<ansLittle[i]<<" "; } cout<<endl; //输出窗口中最大的数 for(int i=0;i<ansBig.size();i++){ cout<<ansBig[i]<<" "; } return 0; }
想要了解单调栈的话,也可以看看这篇文章,这篇文章里前面的介绍和伪代码个人认为很好,帮了我很大的忙。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。