單調(diào)棧和單調(diào)隊(duì)列

單調(diào)棧和單調(diào)隊(duì)列

  • 單調(diào)棧

找到每個(gè)數(shù)左邊離這個(gè)數(shù)最近的數(shù)

這種數(shù)據(jù)結(jié)構(gòu)適用的提醒似乎只有單調(diào)棧問題。

image-20220214210421983
// 暴力做法
for(int i = 0; i<n ;i++){
  for(int j = i-1; j>=0 ;j--){
    if(a[j]<a[i]){
      cout << a[j] << " ";
      break;
    }else{
      cout << "-1" << " ";
    }
  }
}

單調(diào)棧做法蓖康,由于兩個(gè)數(shù)之間存在一種特殊的大小關(guān)系,在比較的時(shí)候可以就刪掉不合格的數(shù)蒜焊,使得最終棧中的數(shù)滿足一個(gè)單調(diào)升序關(guān)系。其實(shí)就是讓暴力做法里棧中的無序數(shù)一直刪刪刪直到變成有序棧泳梆。棧中存放數(shù)是有序的

#include <iostream>
using namespace std;
const int N = 10e5+10;
int stk[N],n,tt;
int main(){
    ios::sync_with_stdio(false); // 優(yōu)化cin輸入榜掌,但是只能提升一點(diǎn)點(diǎn)
    cin.tie(0); // 這個(gè)也能優(yōu)化輸入輸出
    // 還是推薦使用scanf和printf 會(huì)顯著提升,大約10倍
    cin >> n;
    for(int i = 0;i<n;i++){
        int x;
        cin >> x;
        while(tt && stk[tt] >= x) tt--; // 棧如果不為空的話憎账,當(dāng)前棧頂?shù)脑厝羰翘蟮脑挘旬?dāng)前元素彈出棧鼠哥,一直到棧頂?shù)脑乇葂嚴(yán)格小
        if(tt){
            cout << stk[tt] << " ";
        }else{
            cout << -1 << " ";
        }
        
        stk[++tt] = x; // 每一輪做完之后熟菲,把當(dāng)前元素放入棧頂
    }    
    
    return 0;
}
  • 單調(diào)隊(duì)列

典型應(yīng)用:求滑動(dòng)窗口里面的最大值或者最小值

由于窗口的特性,因此窗口問題中的窗口都可以使用隊(duì)列來維護(hù)抄罕。類似單調(diào)棧,把沒有用的元素刪掉呆贿,看看有沒有得到單調(diào)性

拿求滑動(dòng)窗口最小值來說,窗口里的最右邊的數(shù)是最新進(jìn)來的做入,只要最右邊的數(shù)的左邊的數(shù)比該數(shù)大,就可以把所有左邊的數(shù)給刪掉(因?yàn)樽钣疫叺臄?shù)已經(jīng)是最小竟块,我們的目的就是求最小)一直要?jiǎng)h除到使得隊(duì)列中的數(shù)保持遞增浪秘,這樣隊(duì)列有序的話,隊(duì)列頭就是最小值耸携,隊(duì)列尾就是最大值

總結(jié):?jiǎn)握{(diào)棧和單調(diào)隊(duì)列都是讓數(shù)據(jù)結(jié)構(gòu)里的數(shù)據(jù)通過刪除一直保持單調(diào)有序

拿數(shù)組模擬的隊(duì)列和棧相比最大的好處就是 !STL的隊(duì)列和棧就沒有那么快

但是實(shí)際應(yīng)用中STL編譯的時(shí)候夺衍,我們會(huì)開O_{2}優(yōu)化,開完之后其實(shí)速度跟數(shù)組模擬的隊(duì)列差不多快

O2優(yōu)化實(shí)際上是Optimize沟沙,2是優(yōu)化等級(jí)。除了O2優(yōu)化還有O3優(yōu)化尝胆,這是更高等級(jí)的優(yōu)化;還有Ofast含衔、Os等等多種優(yōu)化等級(jí)二庵,對(duì)于有些算法題,使用暴力算法+O2優(yōu)化是可以正常AC的催享;但是注意并不是所有O2優(yōu)化都是正優(yōu)化,有的會(huì)是負(fù)優(yōu)化

[gcc官方關(guān)于O2優(yōu)化的說明] (https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html)

/*
輸出滑動(dòng)窗口中的最大值和最小值
*/
#include <iostream>
using namespace std;
const int N = 10e6+10;
int n,k;
int a[N],q[N]; // a數(shù)組是存儲(chǔ)數(shù)值本身因妙,b數(shù)組是存儲(chǔ)數(shù)值對(duì)應(yīng)的下標(biāo) 

int main(){
    
    scanf("%d%d",&n,&k);
    for(int i = 0; i<n;i++){
        scanf("%d",&a[i]);
    }
    
    int hh = 0,tt = -1; // 初始化隊(duì)列 隊(duì)列實(shí)質(zhì)上就是數(shù)組加兩個(gè)變量
    for(int i = 0; i<n;i++){ // 遍歷每一個(gè)數(shù)
        // 1.檢查隊(duì)頭是否劃出窗口
        if(tt >= hh && i-k+1>q[hh] ){ // 沒有的話
            hh++;
        }
        // 2.當(dāng)前值a[i]與隊(duì)尾值比較 隊(duì)尾值太大就要出隊(duì) 因?yàn)橐獜男〉酱笈?        while(tt >= hh && a[i]<a[q[tt]]) tt--;
        q[++tt] = i; // 把當(dāng)前值得下標(biāo)放入q[]中
        
        // 3. 打印這個(gè)窗口中的最小值 需要窗口在數(shù)組里才會(huì)輸出
        if(i - k + 1 >= 0) printf("%d ",a[q[hh]]);
        
    }
    cout << endl;
    hh = 0,tt = -1; 
    for(int i = 0; i<n;i++){ 
        if(tt >= hh && i-k+1>q[hh] ){ 
            hh++;
        }
        // .當(dāng)前值a[i]與隊(duì)尾值比較 隊(duì)尾值太小就要出隊(duì) 因?yàn)橐獜男〉酱笈?        while(tt >= hh && a[i] > a[q[tt]]) tt--;
        q[++tt] = i; 
        
        if(i - k + 1 >= 0) printf("%d ",a[q[hh]]);
        
    }    
    return 0;
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末票髓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子洽沟,更是在濱河造成了極大的恐慌以故,老刑警劉巖裆操,帶你破解...
    沈念sama閱讀 218,451評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異踪区,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)缎岗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來密强,“玉大人,你說我怎么就攤上這事或渤。” “怎么了薪鹦?”我有些...
    開封第一講書人閱讀 164,782評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)池磁。 經(jīng)常有香客問我,道長(zhǎng)地熄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,709評(píng)論 1 294
  • 正文 為了忘掉前任端考,我火速辦了婚禮揭厚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扶供。我一直安慰自己,他們只是感情好椿浓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著提岔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪左腔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評(píng)論 1 305
  • 那天液样,我揣著相機(jī)與錄音巧还,去河邊找鬼。 笑死麸祷,一個(gè)胖子當(dāng)著我的面吹牛澎怒,可吹牛的內(nèi)容都是我干的阶牍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,320評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼走孽,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了磕瓷?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤困食,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后硕盹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體符匾,經(jīng)...
    沈念sama閱讀 45,686評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瘩例,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評(píng)論 3 336
  • 正文 我和宋清朗相戀三年芒澜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了创淡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痴晦。...
    茶點(diǎn)故事閱讀 39,992評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡琳彩,死狀恐怖誊酌,靈堂內(nèi)的尸體忽然破棺而出露乏,到底是詐尸還是另有隱情碧浊,我是刑警寧澤瘟仿,帶...
    沈念sama閱讀 35,715評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站劳较,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏观蜗。R本人自食惡果不足惜臊恋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評(píng)論 3 330
  • 文/蒙蒙 一墓捻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧砖第,春花似錦撤卢、人聲如沸梧兼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽屎慢。三九已至,卻和暖如春忽洛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背欲虚。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人欣喧。 一個(gè)月前我還...
    沈念sama閱讀 48,173評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像唆阿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子驯鳖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容