单调队列(一套模板通吃)
生活随笔
收集整理的這篇文章主要介紹了
单调队列(一套模板通吃)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
單調隊列
- 利用雙端隊列實現
- 初始化雙端隊列
- 維護隊頭是最大元素
- 維護隊頭是最小元素
- 利用數組實現
- 維護隊頭是最大元素
顧名思義,就是用一點巧妙的方法,使得隊列中的元素全是單調遞增或遞減,常常用來解決滑動窗口的一系列問題。
好了,廢話不多說,上正題。
模板思路在代碼中,超詳細,看完你就悟了。
利用雙端隊列實現
初始化雙端隊列
void init() {//必須從前邊刪while (!q1.empty()) q1.pop_front();while (!q2.empty()) q2.pop_front();}維護隊頭是最大元素
k是區間范圍。
struct node{int order;//對應下標int value;//對應值 }tmp; deque<node>vis; int main() {int n,k,t;scanf("%d%d",&n,&k);for(int i=0;i<n;i++){scanf("%d",&t);//當前值// 當隊列不為空,i是當前值得小標與隊頭元素下標之差大于等于k//表明,雖然你隊頭大,但是已經不在有效范圍了,所以要丟掉if(!vis.empty() && i-vis.front().order>=k) vis.pop_front();// 隊列不為空,因為要維護的隊列是隊頭是最大的,那么這個隊列就//是一個遞減隊列(想一下),所以當前值要比隊尾小才可以,//否則就將隊尾元素丟掉,直到隊尾比當前值小,或隊列為空while(!vis.empty() && vis.back().value<=t) vis.pop_back();tmp.order=i;tmp.value=t;vis.push_back(tmp);if(i>=k-1){printf("%d\n",vis.front().value);}} }維護隊頭是最小元素
```cpp struct node{int order;//對應下標int value;//對應值 }tmp; deque<node>vis; int main() {int n,k,t;scanf("%d%d",&n,&k);for(int i=0;i<n;i++){scanf("%d",&t);//當前值if(!vis.empty() && i-vis.front().order>=k) vis.pop_front();// 其余都一樣,只不過下面這一行,變成當前值要大于隊尾,//結合上面想想就出來了,因為是要維護一個遞增隊列嘛while(!vis.empty() && vis.back().value>=t) vis.pop_back();tmp.order=i;tmp.value=t;vis.push_back(tmp);if(i>=k-1){printf("%d\n",vis.front().value);}} }利用數組實現
維護隊頭是最大元素
vector<int> maxSlidingWindow(vector<int>& nums, int k) {//存的是下標vector<int> q(nums.size(),0); vector<int> vec;int tail = 0;//隊尾指針int head = 0;//隊頭指針for(int i = 0;i< nums.size();i++){//淘汰操作//和上邊對比下,隊列不為空,不就是隊尾指針大于隊頭指針嘛//nums[i] 當前值,nums[q[tail-1]] 隊尾值// 丟掉隊尾元素,不就是將隊尾指針前移嘛while(tail > head && nums[i] >= nums[q[tail-1]]) tail--;//尾插操作q[tail++] = i;//過期頭刪操作//q[head] 不就是對首小標嘛if(i - q[head] >= k) head++;if(i >= k) vec.push_back(nums[q[head]]);}return vec;}看到這里大家有沒有枉然大悟呀
總結
以上是生活随笔為你收集整理的单调队列(一套模板通吃)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一套模板通吃单调栈
- 下一篇: Flask实战----做了一个简易版CS