单调栈的基础

单调栈:

1.单调栈是一种栈数据结构,只能在栈顶进行插入和删除操作

2.单调栈的特点是栈中的元素按照一定的单调性排列,常用的有单调递增和单调递减。

3.在插入新元素时,如果新元素破坏了当前的单调性,则从栈顶删除一部分元素,直到满足单调性要求。这样可以保证栈中的元素保持单调性。

4.单调栈的典型应用是在寻找下一个更大/更小元素的问题。

    

image.png

单调栈分为单调递增栈和单调递减栈两种类型:

1.单调递增栈:

栈中元素从栈底到栈顶递增。在处理序列时,当遇到一个元素时,如果该元素比栈顶元素大,就可以将栈顶元素出栈,直到栈为空或者栈顶元素大于等于当前元素。这样,栈中的元素就是在当前元素之前且比当前元素小的元素。

2.单调递减栈:

栈中元素从栈底到栈顶递减。在处理序列时,当遇到一个元素时,如果该元素比栈顶元素小,就可以将栈顶元素出栈,直到栈为空或者栈顶元素小于等于当前元素。这样,栈中的元素就是在当前元素之前且比当前元素大的元素。

使用单调栈的一般步骤如下:

(1)创建一个空栈。

(2)遍历待处理的序列,对于每个元素执行以下操作:

        1)如果当前元素比栈顶元素大(或小,取决于是递增栈还是递减栈),则持续将栈顶元素出栈,直到栈为空或者栈顶元素满足某种条件(例如比当前元素大或小)。

        2)记录弹出的元素,说明他是单调递减栈或单调递增栈第一个不满足的元素,可以在此元素根据题意进行操作

        3)如果栈不为空,比较当前元素与栈顶元素的大小:

        4)将当前元素入栈。

一个单调递减栈的例子:

进栈元素分别为3,4,2,6,4,5,2,3

3进栈:(3)

3出栈,4进栈:(4)

2进栈:(4,2)

2出栈,4出栈,6进栈:(6)

4进栈:(6,4)

4出栈,5进栈:(6,5)

2进栈:(6,5,2)

2出栈,3进栈:(6,5,3)

以上左端为栈底,右端为栈顶。

单调栈模板:

stack<int> st;

{

   if (栈空 || 栈顶元素大于等于当前比较元素)
   {
       入栈;
   }
   else
   {
       while (栈不为空 && 栈顶元素小于当前元素)
       {
           栈顶元素出栈;
           更新结果;
       }
       当前数据入栈;

   }

}

下面给大家留1道题目:

死神 

描述

L加入了调查组,在与夜神月的激烈斗争后,L还是不敌夜神月,死于月的笔下。但是由于某种不知名的原因,L的灵魂被拖入了死神界,死神们知道了L头脑的强大,所以希望L帮他们解决一个难题后帮助他离开死神界,正常轮回~~~

在死神界的2月31号,死神们都要排队(从左到右排)去参加会议,但是他们被太多死神看到会不舒服。死神的眼睛非常特别,他只能看到第一个比他高的死神(左边或右边的第一个)。

死神们告诉L他们排好队的高度,他们希望L告诉他们谁被最多死神看到。

输入

第1行:一个数N(2<=N<=100000),表示有N个死神。

第2行:有N个数H_I(0小于H_I小于等于5000),表示从左到右第I个死神的高度;

输出

一行,包含一个数,表示被最多死神看到的死神的编号,如果有多解这输出编号最小的那个。

输入样例1                                                                     

5                                                                               

7 8 6 10 9

输出样例1

4

输入格式

输出格式

输入/输出例子1

输入:5
3 2 1 2 3

输出:1

下面是参考代码(c++):

#include<bits/stdc++.h>
using namespace std;
int n,a[100010],f1[100010],f2[100010],s[100010],maxi=1;
stack<int> s1,s2;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++) 
    {
        cin>>a[i];
    }
    for(int i=1;i<=n;i++)
    {
        while(!s1.empty() && a[s1.top()]<=a[i]) 
        {
            s1.pop();
        }
        f1[i]=s1.empty()?0:s1.top();
        s1.push(i);
    }
    for(int i=n;i>1;i--)
    {
        while(!s2.empty() && a[s2.top()]<=a[i]) 
        {
            s2.pop();
        }
        f2[i]=s2.empty()?0:s2.top();
        s2.push(i);
    }
    for(int i=1;i<=n;i++) 
    {
        s[f1[i]]++;
        s[f2[i]]++;
    }
    for(int i=2;i<=n;i++) 
    {
        if(s[i]>s[maxi]) maxi=i;
    }
    cout<<maxi;
    return 0;

(作者创作不易,可以点个关注和点赞吗,谢谢,也欢迎大家评论)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值