zoukankan      html  css  js  c++  java
  • 单调栈

    久闻单调栈,亦使用之,然使用频率过低,常遗忘。今重温,记录在册,往能常记之。

    什么是单调栈

    单调栈就是栈里面存放的数据都是有序的,所以可以分为单调递增栈和单调递减栈两种。

    1. 单调递增栈就是从栈底到栈顶是从大到小
    2. 单调递减栈就是从栈底到栈顶是从小到大

    应用:

    1.视野总和

    描叙:有n个人站队,所有的人全部向右看,个子高的可以看到个子低的发型,给出每个人的身高,问所有人能看到其他人发型总和是多少。
    输入:10 3 7 4  12
    输出:4

    分析:对于每一个元素a[i]找到右边第一个大于他的元素a[j],则j-i-1即为a[i]能看到的人的数目

    比如:a[1]=10,右边第一个大于他的元素为a[5]=12,则第1个人能看到5-1-1=3个人

    a[2]=3,右边第一个大于他的元素为a[3]=7,则第2个人能看到3-2-1=0个人

    a[3]=7,右边第一个大于他的元素为a[5]=12,则第3个人能看到5-3-1=1个人

    a[4]=4,右边第一个大于他的元素为a[5]=12,则第4个人能看到4-3-1=0个人

    单调递减栈:

    初始,栈空

    1:10入栈;

    2:3<10,入栈后能保持栈的递减,则3入栈

    3:7>栈顶元素3,入栈后不能保持栈的递减,则3出栈。同时说明7是第2个人右边第一个比他高的人,则其能看到的人为3-2-1

    4:4<7,入栈后能保持栈的递减,则4入栈

    5:12>栈顶元素4,入栈后不能保持栈的递减,则4出栈。4出栈后,12依然>栈顶元素7,入栈后不能保持栈的递减,则7出栈,说明身高7和4的人右边第一个比他们高的人是12,此时可以计算出这两人能看到的人数。

    由该样例可以看出:每个元素被踢出栈时,将他踢出栈的人,则是他右边第一个比他高的人。

    深思还可以发现,每个元素在栈中时,紧邻他的左边那个元素也是他左边第一个比他高的人。

    总结:单调递减栈可以得出左右都比他高的第一人是谁。

    2.给出一个矩形统计图,它的每个矩形的宽度都为1,高度是题目所给。要你求出这个矩形图中最大面积的长方形。

    矩形统计图的数据为 [4, 3, 2, 5, 6]

    分析:以每一个柱形图的高度为高h,统计其左边最大可达位置,与其右边最大可达位置

    即统计其左边第一个比他小的元素下标x(左边界),与右边第一个比他小的元素下标y(右边界)。 

    则该位置高度为h的矩形面积为h*(y-x-1)、

    由此可以使用递增单调栈来完成

    初始,栈空

    1:4入栈(其左边没有元素,默认左边界为0)

    2:3<4不满足递增性质,4出栈,3入栈,3的左边界同4(0);则高度为4的矩形面积为4*(2-0-1)=4;

    3:2<3不满足递增性质,3出栈,2入栈,2的左边界同3(0);则高度为3的矩形面积为3*(3-0-1)=6;

    4:5>2满足递增性质,5入栈,其左边界为栈中左边元素的下标3

    5:6>5满足递增性质,6入栈,其左边界为栈中左边元素的下标4

    所有元素入栈完毕,此时栈不空,则栈中元素依次出栈,同时计算以其高度为标准的矩形面积

    第一步6 出栈,其右边界为6,左边界为4,则s=(6-4-1)*6=6

    第二步5 出栈,其右边界同上一个出栈元素,也为6,左边界为3,则s=(6-3-1)*5=10

    第三步2 出栈,其右边界同上一个出栈元素,也为6,左边界为0,则s=(6-0-1)*2=10

    3.给定一个整型矩阵map,其中的值只有0和1两种,求其中全是1的所有矩形区域中,最大的矩形区域为1的数量。
    例如:
    1 1 1 0
    其中,最大的矩形区域有3个1,所以返回3。
    再如:
    1 0 1 1
    1 1 1 1
    1 1 1 0
    其中,最大的矩形区域有6个1,所以返回6.

    分析:

    这是一个二维数组,不好直接完成,我们可以尝试压缩成一维数组来完成

    具体如下:以每行为参照标准,计算该行上面每列1的个数,然后使用单调递增栈,这样就求出了每行为基准含有1的个数

    该行上面每列1的个数,统计方法:

    以第i行,第j列为例:

      if(a[i][j]==1) s[i][j]=s[i-1][j]+1;//为上一行该位置1的个数+1,a[i][j]原矩阵,s[i][j]统计第i行第j列其上面有多少个连续出现的1.

      else s[i][j]=0;//如果a[i][j]==0则该位置1的个数是0个,不关心其上面有多少1

    题目来源:

    https://zhuanlan.zhihu.com/p/101785785

    https://blog.csdn.net/lucky52529/article/details/89155694

    单调栈:P1901,p1950,P1565

  • 相关阅读:
    react深入学习(资料,案例)
    match.exec深入学习
    实用插件表格行列隐藏显示
    下拉选项插件的实现
    表格操作eventTable
    [CentOS7] 挂载iso镜像文件到/media目录下
    [CentOS7] 设置开机启动方式(图形界面或命令行)
    [CentOS7] 磁盘分区(gdisk, fdisk)
    [CentOS7] minimal安装后 出现 没有ifconfig 无法ping 无法yum could not retrieve mirrorlist http://mirrorlist.centos.org/
    [C++]C,C++中使用可变参数
  • 原文地址:https://www.cnblogs.com/ssfzmfy/p/14812365.html
Copyright © 2011-2022 走看看