单调栈

转载自:https://blog.csdn.net/zuzhiang/article/details/78134247

定义:

单调栈,顾名思义,是栈内元素保持一定单调性(单调递增或单调递减)的栈。既然是栈,就满足后进先出的特点。与之相对应的是单调队列。

单调栈有以下两个性质:
1、若是单调递增栈,则从栈顶到栈底的元素是严格递增的。若是单调递减栈,则从栈顶到栈底的元素是严格递减的。
2、越靠近栈顶的元素越后进栈。

3、利用单调栈,可以找到从左/右遍历第一个比它小/大的元素的位置

从当前元素a[i]开始向左边找第一个比a[i]小的值/

 for (int i = 0; i < n; i++)
        {
            while (!p.empty() && a[p.top()] >= a[i])//按照大于等于a[i]的规则,从a[i]开始,向左边可以延伸最远的数的下标
                p.pop();
            if (p.empty())//说明a[i]左边的所有数都大于等于a[i]
                l[i] = 0;
            else//找到就记录从a[i]开始向左边寻找大于等于a[i]的最大边界下标
                l[i] = p.top() + 1;
            p.push(i);
        }

 从当前元素a[i]开始向右边找第一个比a[i]小的值

while (!p.empty())//记得清空栈
            p.pop();
        for (int i = n - 1; i >= 0; i--)//往右边找第一个比a[i]小的数
        {
            while (!p.empty() && a[p.top()] >= a[i])
                p.pop();
            if (p.empty())
                r[i] = n - 1;
            else
                r[i] = p.top() - 1;
            p.push(i);
        }

实现:

例如实现一个单调递增的栈,比如现在有一组数10,3,7,4,12。从左到右依次入栈,则如果栈为空或入栈元素值小于栈顶元素值,则入栈;否则,如果入栈则会破坏栈的单调性,则需要把比入栈元素小的元素全部出栈。单调递减的栈反之。


10入栈时,栈为空,直接入栈,栈内元素为10。

3入栈时,栈顶元素10比3大,则入栈,栈内元素为10,3。

7入栈时,栈顶元素3比7小,则栈顶元素出栈,此时栈顶元素为10,比7大,则7入栈,栈内元素为10,7。

4入栈时,栈顶元素7比4大,则入栈,栈内元素为10,7,4。

12入栈时,栈顶元素4比12小,4出栈,此时栈顶元素为7,仍比12小,栈顶元素7继续出栈,此时栈顶元素为10,仍比12小,10出栈,此时栈为空,12入栈,栈内元素为12。

伪代码

/*
* 本伪代码对应的是单调递减栈 
*共n个元素,编号为0~n-1
*/
while(栈为空) 栈顶元素出栈; //先清空栈
a[n]=-1;
for(i=0;i<=n;i++)
{
    if(栈为空或入栈元素大于等于栈顶元素) 入栈;
    else 
    {
        while(栈非空并且栈顶元素大于等于入栈元素)
        {
            栈顶元素出栈;
            更新结果; 
        } 
        将最后一次出栈的栈顶元素(即当前元素可以拓展到的位置)入栈; 
        更新最后一次出栈的栈顶元素其对应的值; 
    }      
}
输出结果; 

应用:

以上就是一个单调栈的定义及其实现,下面就来说一下它可以解决哪些问题。其实我也不能给出证明,以证明它为什么能完成这些功能,只是简单的把它的用途说一下,碰到问题时就需要大家灵活运用了。


1.最基础的应用就是给定一组数,针对每个数,寻找它和它右边第一个比它大的数之间有多少个数。

2.给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列的长度最大。

3.给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列所有元素和最大。

实战练习:

一、应用一:poj3250 单调递减栈

https://www.cnblogs.com/-citywall123/p/10769634.html

二、应用二:poj 2559 单调递增栈

https://www.cnblogs.com/-citywall123/p/10770468.html

三、应用三:poj 2796

https://www.cnblogs.com/-citywall123/p/10770825.html

原文地址:https://www.cnblogs.com/-citywall123/p/10759351.html