单调栈

单调栈

要想理解单调栈,就得知道它是什么?
定义:单调栈是指栈中元素按照单调递增(或递减)的顺序存在与栈中,所以它分为单调递增栈,和单调递减栈。如果允许相等,则还可以分为单调非递增栈,和单调非递减栈。所以它既有栈的性质(先进后出),又拥有单调性质,因此叫做单调栈。
那么它有什么作用呢?
作用:利用单调栈,可以找到从左(或者右)遍历第一个比它小(或者大)的元素或者位置。
也可以说是 求某组数以其中某一个数字为最小值的最大延伸区间
比如 {2 3 2 5 1 4},以第一个2为最小值可以延伸的区间为{2, 3, 2, 5}
应用:我们来看一道例题。

直方图是由在公共基线处对齐的一系列矩形组成的多边形。
矩形具有相等的宽度,但可以具有不同的高度。
例如,图例左侧显示了由高度为2,1,4,5,1,3,3的矩形组成的直方图,矩形的宽度都为1:
2559_1.jpg
通常,直方图用于表示离散分布,例如,文本中字符的频率。
现在,请你计算在公共基线处对齐的直方图中最大矩形的面积。
图例右图显示了所描绘直方图的最大对齐矩形。
输入格式
输入包含几个测试用例。
每个测试用例占据一行,用以描述一个直方图,并以整数n开始,表示组成直方图的矩形数目。
然后跟随n个整数h1,…,hn。
这些数字以从左到右的顺序表示直方图的各个矩形的高度。
每个矩形的宽度为1。
同行数字用空格隔开。
当输入用例为n=0时,结束输入,且该用例不用考虑。
输出格式
对于每一个测试用例,输出一个整数,代表指定直方图中最大矩形的区域面积。
每个数据占一行。
请注意,此矩形必须在公共基线处对齐。
数据范围
1≤n≤100000,
0≤hi≤1000000000
输入样例:
7 2 1 4 5 1 3 3
4 1000 1000 1000 1000
0
输出样例:
8
4000
一般方法:我们对于每一个元素,可以向左向右遍历,找出第一个小于元素的下标,因为我们的高就等于a[i],所以我们只要求出宽就行了,宽=right-left-1;
因此我们就可以求出面积了,而在向左向右找的时候我们可以自定义一个函数用来求面积,然后再找出一个最大的面积就好。
好像这似乎与我们今天所学的单调栈没什么关联,别急!
这就来告诉你,单调栈的好处,因为它可以节省时间复杂度!
单调栈方法:在我们求面积的时候,我们为了找出最大的面积,我们会向左向左找比自己高的直方形,这是不是和我们单调栈的作用有关,没错,这就是我们用单调栈的原因。一旦大于栈顶元素的值就入栈,小于就出栈,并在出栈的时候求出面积,并记录其值,然后通过比较求出最大值。

求最大面积的函数如下

int dandiao(int n)//定义一个用来求面积的函数(模块化)
{
    long long int tail,t,max,ans,i;
    a[n+1]=0;
    tail=0;//初始化
    max=0;//用来记录最大面积
    house[tail]=-1;//因为刚开始的时候,必须入栈,所以设置一个负数,来保证入栈
    for(i=1; i<=n+1; i++)
    {
        if(a[i]>house[tail])//一旦大于栈顶元素就入栈
        {
            house[++tail]=a[i];//入栈
            b[tail]=1;//1代表每个直方形的宽度(是题中所给的)
        }
        else//出栈,求面积
        {
            t=0;
            while(house[tail]>a[i])//小于栈顶元素,则将栈顶元素出栈,同时求面积
            {
                t=t+b[tail];//t用来记录宽度
                ans=house[tail]*t;//求出面积
                if(max<ans)//记录最大值
                    max=ans;
                tail--;
            }
            house[++tail]=a[i],b[tail]=t+1;//进栈
        }
    }
    return max;
}

注意:1.注意宽度的累加。2.在出栈完之后记得将该元素进栈,以保持栈的单调。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值