1. 程式人生 > 其它 >單調棧與佇列的應用

單調棧與佇列的應用

1、單調棧一般是求數列某個數最左側第一個大於或小於這個數的數

題目如下:

程式碼如下:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e5 + 10;

int stk[N], top;

int n;

int main()
{
    cin >> n;
    
    while (n -- )
    {
        int x;
        scanf("%d", &x);
        while(top && stk[top] >= x) top --; //棧不空且大於這個數的話,則彈出
        if(top) printf("%d ", stk[top]); //棧不空的話,棧頂則是小於它的第一個數。
        else printf("-1 ");
        stk[++ top] = x; //壓棧
    }
}

2、單調佇列的典型應用,滑動視窗

題目如下:

程式碼如下:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e6+10;

int a[N], q[N];
int hh, tt = -1;

int main()
{
    int n, k;
    cin >> n >> k;
    for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
    
    for (int i = 0; i < n; i ++ )
    {
        if(hh <= tt && q[hh] < i- k + 1) hh ++; 
        /*如果隊頭(佇列存的是陣列下標,q[hh]
        代表隊頭是陣列的第幾個數字)已經出了視窗,則用hh++的方式讓隊頭始終在窗口裡*/
        while(hh <= tt && a[q[tt]] >= a[i]) tt --;
        /*如果佇列不空,而且隊尾元素大於當前新進佇列元素,則移除隊尾元素,使佇列單調 */
        
        q[++ tt] = i;
        if(i >= k - 1)printf("%d ",a[q[hh]]);
    }
    
    puts("");
    
    tt = -1, hh = 0; // 勿忘記清空佇列
     for (int i = 0; i < n; i ++ )
    {
        if(hh <= tt && q[hh] < i- k + 1) hh ++; 
        /*如果隊頭(佇列存的是陣列下標,q[hh]
        代表隊頭是陣列的第幾個數字)已經出了視窗,則用hh++的方式讓隊頭始終在窗口裡*/
        while(hh <= tt && a[q[tt]] <= a[i]) tt --;
        /*同理*/
        
        q[++ tt] = i;
        if(i >= k - 1)printf("%d ",a[q[hh]]);
    }
    
}

3、總結

牢記單調棧與佇列的應用。

本文來自部落格園,作者:Medjay,轉載請註明原文連結:https://www.cnblogs.com/Medjay/p/15805038.html