单调栈和单调队列

单调栈和单调队列

  • 单调栈

找到每个数左边离这个数最近的数

这种数据结构适用的提醒似乎只有单调栈问题。

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" << " ";
    }
  }
}

单调栈做法,由于两个数之间存在一种特殊的大小关系,在比较的时候可以就删掉不合格的数,使得最终栈中的数满足一个单调升序关系。其实就是让暴力做法里栈中的无序数一直删删删直到变成有序栈。栈中存放数是有序的

#include <iostream>
using namespace std;
const int N = 10e5+10;
int stk[N],n,tt;
int main(){
    ios::sync_with_stdio(false); // 优化cin输入,但是只能提升一点点
    cin.tie(0); // 这个也能优化输入输出
    // 还是推荐使用scanf和printf 会显著提升,大约10倍
    cin >> n;
    for(int i = 0;i<n;i++){
        int x;
        cin >> x;
        while(tt && stk[tt] >= x) tt--; // 栈如果不为空的话,当前栈顶的元素若是太大的话,把当前元素弹出栈,一直到栈顶的元素比x严格小
        if(tt){
            cout << stk[tt] << " ";
        }else{
            cout << -1 << " ";
        }
        
        stk[++tt] = x; // 每一轮做完之后,把当前元素放入栈顶
    }    
    
    return 0;
}
  • 单调队列

典型应用:求滑动窗口里面的最大值或者最小值

由于窗口的特性,因此窗口问题中的窗口都可以使用队列来维护。类似单调栈,把没有用的元素删掉,看看有没有得到单调性

拿求滑动窗口最小值来说,窗口里的最右边的数是最新进来的,只要最右边的数的左边的数比该数大,就可以把所有左边的数给删掉(因为最右边的数已经是最小,我们的目的就是求最小)一直要删除到使得队列中的数保持递增,这样队列有序的话,队列头就是最小值,队列尾就是最大值

总结:单调栈和单调队列都是让数据结构里的数据通过删除一直保持单调有序

拿数组模拟的队列和栈相比最大的好处就是 !STL的队列和栈就没有那么快

但是实际应用中STL编译的时候,我们会开O_{2}优化,开完之后其实速度跟数组模拟的队列差不多快

O2优化实际上是Optimize,2是优化等级。除了O2优化还有O3优化,这是更高等级的优化;还有Ofast、Os等等多种优化等级,对于有些算法题,使用暴力算法+O2优化是可以正常AC的;但是注意并不是所有O2优化都是正优化,有的会是负优化

[gcc官方关于O2优化的说明] (https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html)

/*
输出滑动窗口中的最大值和最小值
*/
#include <iostream>
using namespace std;
const int N = 10e6+10;
int n,k;
int a[N],q[N]; // a数组是存储数值本身,b数组是存储数值对应的下标 

int main(){
    
    scanf("%d%d",&n,&k);
    for(int i = 0; i<n;i++){
        scanf("%d",&a[i]);
    }
    
    int hh = 0,tt = -1; // 初始化队列 队列实质上就是数组加两个变量
    for(int i = 0; i<n;i++){ // 遍历每一个数
        // 1.检查队头是否划出窗口
        if(tt >= hh && i-k+1>q[hh] ){ // 没有的话
            hh++;
        }
        // 2.当前值a[i]与队尾值比较 队尾值太大就要出队 因为要从小到大排
        while(tt >= hh && a[i]<a[q[tt]]) tt--;
        q[++tt] = i; // 把当前值得下标放入q[]中
        
        // 3. 打印这个窗口中的最小值 需要窗口在数组里才会输出
        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++;
        }
        // .当前值a[i]与队尾值比较 队尾值太小就要出队 因为要从小到大排
        while(tt >= hh && a[i] > a[q[tt]]) tt--;
        q[++tt] = i; 
        
        if(i - k + 1 >= 0) printf("%d ",a[q[hh]]);
        
    }    
    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容