LeetCode 84.柱状图中最大的矩形 | 单调栈的使用 | 解题思路及算法 Java

给定(n)个非负整数,用来表示柱状图中每个柱子的高度。每个柱子相邻且宽度为1。
求这个柱状图中能容纳的最大矩形的面积。

对于一个柱状图中的最大矩形,我们可以观察出如下性质:

根据上面两个性质,我们可以得出一个求最大矩阵的算法:

对于每一个柱子(i),如果我们知道它左边和右边第一个比它矮的柱子的位置(left,\ right),我们就可以计算出以这个柱子(i)为顶边的最大矩形,其面积为((right-left-1)\times height[i])。
对于每个柱子都进行上述计算,取其中的最大值,即为整个柱状图中的最大矩形。

那如何求每个柱子左右两边第一个比它矮的柱子位置呢?可以拆解为两个问题:1. 找到每个柱子右边第一个比它矮的柱子的位置。2. 找到每个柱子左边第一个比它矮的柱子的位置。
像这样具有单调性的题目,应该使用单调栈解决。下面演示单调递增栈的细节。

记一个数组(right),大小为(n)即总元素的个数。用来记录每个(index)对应的右边的第一个小于(height[index])的元素的(index’)。我们将其初始化为(n),即默认右边第一个小于(height[index])的元素的位置为(n)。
维护一个栈(存的是元素的index),对于每一个新元素(a),如果大于等于栈顶元素,直接把其index push进栈;如果比栈顶元素小,把栈顶元素对应的(right[i])设为(a)的(index),再对栈进行pop操作。如此反复直到(a)大于等于栈顶元素,再把其index push进栈。循环完了,如果栈中还剩下元素。这些元素的右边没有比它们小的元素,于是就默认为(n)了。

通过上述过程我们可以得到每个柱子右边第一个比它矮的柱子的位置。同理可以得到每个柱子左边第一个比它矮的柱子的位置。但是通过观察可以发现:每个元素的index在被push进入栈的时候其左边界就可以”确定了”:为栈顶的index。解释如下:

如果 栈中没两个相邻的元素的高不同,我们在进行push进栈的时候,栈顶的元素的值已经小于我们将push进去元素的值了。因此每个元素在被push的时候左边界就确定了,为栈顶的值。

如果 栈中有高相同的元素相邻,如(a,b:height[a]=height[b],a

其实这样的不准确并不影响求以(a)或(b)为上边的矩形的面积。既然(height[a]=height[b]),并且它们在栈中相邻,说明它们中间没有比它们小的值。对于元素(a),其左边界是准确的,即(height[left[a]]

所以我们可以在求右边界的时候就可以确定左边界的位置。

详细代码如下:Java

class p84 {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length, maxSize = 0;
        Deque mono_stack = new ArrayDeque();
        int[] left = new int[n];
        int[] right = new int[n];
        Arrays.fill(right, n);
        for (int i = 0; i < n; i++) {
            while (!mono_stack.isEmpty() && heights[mono_stack.peek()] > heights[i]) {
                right[mono_stack.peek()] = i;
                mono_stack.pop();
            }
            left[i] = mono_stack.isEmpty() ? -1 : mono_stack.peek();
            mono_stack.push(i);
        }
        for (int i = 0; i < n; i++) {
            maxSize = Math.max(maxSize, (right[i] - left[i] - 1) * heights[i]);
        }
        return maxSize;
    }
}

空间复杂度:使用两个数组存左右边界,复杂度为(O(n))。
时间复杂度:遍历每个元素为(n),在遍历中进行pop、push等操作,但是pop和push的总操作量小于(O(2n)),最后遍历计算最大面积(O(n))。因此总时间复杂度为(O(n))。

Original: https://www.cnblogs.com/liuzhch1/p/16124393.html
Author: liuzhch1
Title: LeetCode 84.柱状图中最大的矩形 | 单调栈的使用 | 解题思路及算法 Java

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/606690/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 学习linux(centos7)记录的笔记

    此随笔用于记录学习《linux鸟哥的私房菜》过程中1.遇到的问题及解决的过程 2.有必要记录的重要内容 3.对应书上操作的记录 开始于2021年6月18号 一个磁盘的分区通过格式化…

    Linux 2023年6月6日
    088
  • 职场最讨厌的人,没有之一

    人物背景: 姓名:春绿,性别:未知,年龄:不详,工龄:菜鸟,人物特点:爱管闲事,管不住自己的嘴,情商约等于0.000001 人物故事: 1、领导给小明安排了一个工作,被春绿听到了,…

    Linux 2023年6月13日
    0103
  • C 中的字符数组

    在C语言中没有专门的字符串变量,字符串实际上是使用 null 字符 \0 终止的一维字符数组。因此,一个以 null 结尾的字符串,包含了组成字符串的字符。通常用一个 字符数组来存…

    Linux 2023年6月13日
    093
  • SSH免密登录

    SSH免密登录实现三步: 客户端生成公钥和私钥 上传公钥到服务端 SSH免密登录 (1) 客户端生成和公钥和私钥 ssh-keygen 一路回车即可,默认会在~/.ssh/目录下创…

    Linux 2023年6月7日
    096
  • 6.19(junit–>在maven和Spring中的使用)

    写文章要不忘初心,今天也要继续努力~ 白盒测试:是一种测试用例设计方法,在这里盒子指的是被测试的软件,白盒,顾名思义即盒子是可视的,你可以清楚盒子内部的东西以及里面是如何运作的,因…

    Linux 2023年6月7日
    0100
  • AOP+Redis+SpringCache翻译字典状态

    1,字典表Or枚举类? 项目里有很多标识状态的字段,比如订单状态:0-未支付,1-已支付,2-已取消。或者性别sex: 0-未知,1-男,2-女 。等等。一般这种我们都会建相应的枚…

    Linux 2023年5月28日
    0117
  • Linux之vim编辑器

    1.vim三种模式 模式 操作 可视模式 可查看内容 编辑模式 可查看可修改内容 命令行模式 给vim发送控制命令,可查看内容 注:打开文件,默认是可视模式 2.三种模式的切换 可…

    Linux 2023年6月6日
    095
  • CA证书介绍与格式转换

    PKCS 公钥加密标准(Public Key Cryptography Standards, PKCS),此一标准的设计与发布皆由RSA资讯安全公司(英语:RSA Security…

    Linux 2023年6月6日
    088
  • Redis监控技巧(转)

    来自:http://blog.nosqlfan.com/html/4166.html Redis 监控最直接的方法当然就是使用系统提供的 info 命令来做了,你只需要执行下面一条…

    Linux 2023年5月28日
    099
  • 【证券从业】金融基础知识-第五章 债券01

    注1:后续学习并整理到第八章,全书完结后再合并成一个笔记进行源文件分享 注2:本章内容巨多,大约分为两篇文章记录消化 posted @2022-06-08 01:30 陈景中 阅读…

    Linux 2023年6月13日
    079
  • [随记]-linux侦听端口的4种方法

    侦听 192.168.0.1 服务器上的 10086 端口是否打开 1. telnet telnet是windows 内置的功能,当然 linux 也有。用法: tenlet 19…

    Linux 2023年6月6日
    0108
  • Kubernetes中的网络

    一、引子 既然Kubernetes中将容器的联网通过插件的方式来实现,那么该如何解决这个的联网问题呢? 如果你在本地单台机器上运行docker容器的话注意到所有容器都会处在 doc…

    Linux 2023年6月14日
    096
  • Linux常用扩展

    目录 ~ ? * [] {} 1. ~ 代表当前用户的home目录 pwd ~$ /home/user/ ls ~$ a touch ~/b ls ~$ a b ~ 等于/home…

    Linux 2023年6月7日
    084
  • Spring Boot:使用Redis存储技术

    综合概述 Redis是一个开源免费的高性能key-value数据库,读取速度达110000次/s,写入速度达81000次/s。Redis支持丰富的数据类型,如Lists, Hash…

    Linux 2023年5月28日
    0107
  • Firefox浏览器的一些配置

    一、在新标签页打开书签 1、打开Firefox浏览器,地址栏输入 about:config。 2、选择”接受风险并继续”。 3、搜索 browser.tab…

    Linux 2023年6月6日
    0115
  • 匿名远程启动jenkins的job

    安装jenkins插件Build Authorization Token Root job配置中的构建触发器,勾选触发远程构建,输入要用的令牌,如soul 通过jenkins地址调…

    Linux 2023年6月6日
    0131
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球