LeetCode No.84

最大矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。


LeetCode图

以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。


LeetCode图

图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。

示例:
输入: [2,1,5,6,2,3]
输出: 10

题目分析

  1. 想要知道最大矩形,肯定先要知道每根柱子怎么形成矩形的
  2. 对柱子 i,高度为 hi,以i为中心往两边扩展,只要碰到的柱子高度 Hj>=hi,那么形成的矩形必然是以 hi 为高构造。
  3. 假如 Hj<hi,那么这个矩形的高就是新的 Hj,而这个 Hj 构造的矩形必然会出现在以柱子 j 为中心扩展的时候,所以不必考虑降低现在的高度。
  4. 所以对柱子 i 的扩展,往左右两边找,碰到矮的停下来,确定两边边界,边界高度 Hj>=hi,这个即是这个 i 自己能做出来的最大矩形。

可以双重循环扫描,但不是重点,这里学习题解大神的栈思路。

题解分析:栈保留边界

  1. 首先有一层主循环遍历所有柱子,从左到右,当前柱子为 i。

  2. 我们目的是要找i的两个边界,因为是从左到右扫描,即我们可以顺手找到 i 的右边界。只要扫描时碰到比 i 矮的就知道这个是右边界了。

  3. 但是碰到比 i 高或者相等的柱子 j 怎么办呢?j 不会是 i 的边界 ,但我们也要找 j 的边界。因此我们要把未处理的 i 和 j 都留下来。

  4. 而继续往后找的时候, i 的右边界x 必然是 j 的右边界或者之外 (hi<=hj) 。
    因此对于下一个柱子 x:
    4.1 假如我们先判断 x 是不是 i 的边界,假如它是,它也不一定就是 j 的右边界 ,我们还得用 x 和 j 比较一次。假如它不是,它也不一定就不是 j 的右边界,还是得 x j 比较一次,所以先判定 i 的边界很鸡肋
    4.2 假如先判断 x 是不是更高的 j 的右边界,假如它不是,那么肯定也不是 i 的边界,假如它是,那么可以继续判定是不是更矮的 i 的右边界。

  5. 因此,我们的扫描过程是这样的,从左到右,且保留的柱子高度递增(因为只要更高的才会保留,否则是作为右边界判定)。
    且判定的顺序是高的在前,低的在后,即新的在前,旧的在后,因此保留柱子的数据结构是:栈
    因此遇到一个新柱子,与栈顶比较,更高则继续压栈。更低则是栈顶的右边界,然后栈顶出栈,判定是不是下一个栈顶的右边界。

  6. 右边界解决了,我们还需要确定每个柱子 i 的左边界,左边界肯定在左边 , 并且左边界也要比 i 矮,而我们的栈又是高度递增的= =+显然,我们可以利用出栈过程。
    在栈顶确定了右边界,然后出栈的时候:
    6.1 下面的那个柱子高度大于【栈顶右边界高度Hr】,那么这个柱子不是左边界,而可以组成这个矩形(因为有右边界后,矩形最低高度是Hr,只要高于Hr,都是)我们继续出栈寻找即可。
    6.2 即一直出栈,直到出了个高度小于等于【栈顶右边界高度Hr】的柱子 x ,那么 x 就是上面这个矩形的左边界。

出栈到边界了怎么办?在数组开头预备一个0作为栈底标志位结束出栈。
同样压栈到边界了怎么办?在数组结尾预备一个0作为启动出栈的标志位。

  1. 此时 i 的左右边界都能找到,高度为 i ,计算面积。

总之精髓在于出栈过程,从栈顶的右边界,一直出栈到满足的左边界,中间这些柱子形成当前最大矩形。

题解代码

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) 
    {
        //题解学习
        std::stack<int> Lefts;
        heights.insert(heights.begin(),0);//补0作为边界判断
        heights.insert(heights.end(),0);
        int result=0;
        int temp;
        for(int i=0;i<heights.size();i++)
        {   
            //栈单调递增,当碰到一个i 比栈顶矮,则它必是栈顶的右边界
            //再逐渐出栈,每次出栈循环,都是栈顶作为中心,而栈单调递增,栈顶下面一个更矮的必是栈顶的左边界,左右边界确定,则栈顶位置能形成的矩阵面积可计算完毕。
            //直到栈顶比 i 还矮,那 i 就不能作为右边界了 ,栈顶此时的右边界也找不到,则 i 入栈待命当左边界,然后for下一轮
            while(Lefts.empty()!=true && heights[Lefts.top()]>heights[i])//找到比栈顶矮的柱子,即栈顶柱子的右边界
            {     
                temp=Lefts.top();
                Lefts.pop();
                result = max(result, (i - Lefts.top()-1)*heights[temp]);
            }
            Lefts.push(i);
        }

        return result;


    }
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容

  • 题目 给定一个整数map,其中的值只有0和1两种,求其中全是1的所有矩形区域中最大的矩形区域为1的数量。  例如:...
    呤雪情枫阅读 551评论 0 1
  • 题目描述(困难难度) 给一个柱状图,输出一个矩形区域的最大面积。 解法一 暴力破解 以题目给出的例子为例,柱形图高...
    windliang阅读 614评论 0 0
  • 题目地址: https://leetcode-cn.com/problems/largest-rectangle-...
    xuzhougeng阅读 266评论 0 1
  • //这是19号的话~拖了一天了以后不能随便发pyp了//🙂我们还是很水的,hduoj做到最后脑壳疼现在还是先把今天...
    Vincy_ivy阅读 1,651评论 0 2
  • 杀死一只知更鸟,p48 今日下雨
    几近光明阅读 207评论 0 0