Leecode热题100-84.柱状图中的最大矩形

news2024/12/30 8:26:33

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

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

示例 1:

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10

示例 2:

输入: heights = [2,4]
输出: 4

提示:

  • 1 <= heights.length <=105
  • 0 <= heights[i] <= 104

思路都在代码注释里,自己看,看不懂的留言或者私信,看到第一时间解答

class Solution {
    /**这个题第一感觉是用的单调栈的解法,这个最大的矩形必定以某一个柱子的高度为最低高度
    我们对于每个柱子,求出它左边第一个比它小的(left)和右边第一个比它小的(right)则right-left-1就是以这个柱子为最低高度的矩形的宽度
    所有的这些宽度*高度里的最大值就是我们的答案*/
    public int largestRectangleArea(int[] heights) {
        /**如果只有一个,那没啥说的,返回它的高度就行了,因为它的宽度是1 */
        if(heights.length == 1) {
            return heights[0];
        }
        /**如果是两个,我们可以特殊处理也可以不特殊处理,这里我不特殊处理了,直接用单调栈来处理
        单调栈的核心是nearLess数组,我们使用单独的方法去求这个*/
        int[][] nearLess = getNearLess(heights);
        /**有了这个数组之后我们就可以直接比较求答案了 */
        int ans = 0;
        for(int i = 0; i < heights.length; i++) {
            /**我们这里left和right可以直接用,因为我们在getNearLess里已经取巧处理了 */
            int left = nearLess[i][0];
            int right = nearLess[i][1];
            ans = Math.max(ans, (right - left - 1) * heights[i]);
        }
        return ans;
    }

    public int[][] getNearLess2(int[] heights) {
        /**定义返回结果 */
        int[][] nearLess = new int[heights.length][2];
        /**定义单调栈,我们栈里的数据是栈底到栈顶依次变大的,也就是栈顶是最小值,如果出现更小的就把大的弹出 */
        Stack<Integer> minStack = new Stack<>();
        /**遍历数组依次入栈 */
        for(int i = 0; i < heights.length; i++) {
            while(!minStack.isEmpty() && heights[minStack.peek()] > heights[i]) {
                /**把大的弹出 */
                int popIndex = minStack.pop();
                /**i是造成popIndex这个数弹出的,也就是右边第一个小于它的数的下标 */
                nearLess[popIndex][1] = i;
                /**popIndex左边第一个比它小的是它压着的,如果下面没了(栈空了),就写-1*/
                nearLess[popIndex][0] = minStack.isEmpty()? -1 : minStack.peek();
            }
            /**当前已经满足放入的条件了,放入当前数 */
            minStack.push(i);
        }
        /**结算栈中剩余的元素 */
        while(!minStack.isEmpty()) {
            int popIndex = minStack.pop();
            /**剩余需要结算的数右边没有比它小的,这里就写heigths.length了,这里是为了主方法计算方便,一般别的地方我写-1 */
            nearLess[popIndex][1] = heights.length;
            /**popIndex左边第一个比它小的是它压着的,如果下面没了(栈空了),就写-1*/
            nearLess[popIndex][0] = minStack.isEmpty()? -1 : minStack.peek();
        }
        return nearLess;
    }

    public int[][] getNearLess(int[] heights) {
        /**定义返回结果 */
        int[][] nearLess = new int[heights.length][2];
        /**定义单调栈,我们栈里的数据是栈底到栈顶依次变大的,也就是栈顶是最小值,如果出现更小的就把大的弹出,这里我替换成数组用于节约常数时间 */
        int[] minStack = new int[heights.length];
        int stackSize = 0;
        /**遍历数组依次入栈 */
        for(int i = 0; i < heights.length; i++) {
            while(stackSize != 0 && heights[minStack[stackSize - 1]] > heights[i]) {
                /**把大的弹出 */
                int popIndex = minStack[--stackSize];
                /**i是造成popIndex这个数弹出的,也就是右边第一个小于它的数的下标 */
                nearLess[popIndex][1] = i;
                /**popIndex左边第一个比它小的是它压着的,如果下面没了(栈空了),就写-1*/
                nearLess[popIndex][0] = stackSize == 0? -1 : minStack[stackSize - 1];
            }
            /**当前已经满足放入的条件了,放入当前数 */
            minStack[stackSize++] = i;
        }
        /**结算栈中剩余的元素 */
        while(stackSize != 0) {
            int popIndex = minStack[--stackSize];
            /**剩余需要结算的数右边没有比它小的,这里就写heigths.length了,这里是为了主方法计算方便,一般别的地方我写-1 */
            nearLess[popIndex][1] = heights.length;
            /**popIndex左边第一个比它小的是它压着的,如果下面没了(栈空了),就写-1*/
            nearLess[popIndex][0] = stackSize == 0? -1 : minStack[stackSize - 1];
        }
        return nearLess;

    }
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2185111.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQL SERVER 从嫌弃存储到爱上存储过程我给存储过程开发了版本控制工具和远程调试功能...

优缺点 SQL SERVER 爱上存储过程我给存储过程开发了版本控制工具和远程调试功能 先说说 存储过程的优缺点吧存储过程的优点 提高执行效率&#xff1a;存储过程是预编译的&#xff0c;执行速度较快&#xff0c;减少了网络传输量。 减少开发工作量&#xff1a;存储过程可以将复杂…

删除GitHub仓库的fork依赖 (Delete fork dependency of a GitHub repository)

解除fork仓库依赖的原因 在 Fork 了一个仓库&#xff0c;进行了大量修改&#xff0c;导致与父仓库的功能差异很大。 在每次 Pull Request 的默认目标分支是父仓库&#xff0c;很容易就会 PR 到父仓库里。 Fork 的仓库被其他人提出贡献并使用了&#xff0c;但不能显示贡献者…

【Python报错已解决】TypeError: not enough arguments for format string

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

国庆普及模拟2总结

目录 题目链接&#xff1a; 官方题解&#xff1a; 概述&#xff1a; 总结反思&#xff1a; 题目 T1: 题目分析&#xff1a; 错误代码&#xff1a; 错因&#xff1a; &#xff21;&#xff23;代码&#xff1a; T2&#xff1a; 题目分析&#xff1a; 赛时代码&#xf…

【Nacos架构 原理】内核设计之Nacos通信通道

文章目录 Nacos通信通道 &#xff08;长链接&#xff09;现状背景场景分析配置服务 长链接核心诉求功能性诉求负载均衡连接生命周期 Nacos通信通道 &#xff08;长链接&#xff09; 现状背景 Nacos 1.X 版本 Config/Naming 模块各自的推送通道都是按照自己的设计模型来实现的…

链表OJ经典题目及思路总结(二)头结点

系列文章目录 链表OJ经典题目及思路总结&#xff08;一&#xff09;双指针 链表OJ经典题目及思路总结&#xff08;二&#xff09;头结点 文章目录 系列文章目录前言1.建立新链表1.1 移除链表元素 2.哨兵位的头结点2.1 链表分割2.2 合并两个有序链表 3.CV工程师总结 前言 对于…

Python笔记 - 利用装饰器设计注解体系

认识注解 注解&#xff08;Annotation&#xff09;是一种用于为代码添加元数据的机制。这些元数据可以在运行时被访问&#xff0c;用于为代码元素&#xff08;如类、方法、字段等&#xff09;提供额外的信息或指示。 由于Python中装饰器只能装饰类和方法&#xff0c;因此也只…

C动态内存管理

前言&#xff1a;不知不觉又过去了很长的一段时间。今天对C语言中的动态内存管理进行一个系统性的总结。 1 为什么要有动态内存分配 在C语言中&#xff0c;使用int&#xff0c;float&#xff0c;double&#xff0c;short等数据内置类型以及数组不是也可以开辟内存空间吗&…

《算法岗面试宝典》重磅发布!

大家好&#xff0c;历时半年完善&#xff0c;《算法岗面试宝典》 终于可以跟大家见面了。 最近 ChatGPT 爆火&#xff0c;推动了技术圈对大模型算法场景落地的热情&#xff0c;就业市场招聘人数越来越多&#xff0c;算法岗一跃成为竞争难度第一的岗位。 岗位方向 从细分方向…

李宏毅深度学习-梯度下降和Normalization归一化

Gradient Descent梯度下降 ▽ -> 梯度gradient -> vector向量 -> 下图中的红色箭头&#xff08;loss等高线的法线方向&#xff09; Tip1: Tuning your learning rates Adaptive Learning Rates自适应 通常lr会越来越小 Adaptive Learning Rates中每个参数都给它不同…

110.WEB渗透测试-信息收集-ARL(1)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;109.WEB渗透测试-信息收集-FOFA语法&#xff08;9&#xff09; 信息收集自动化工具-灯塔…

黑马头条day6-kafka及异步通知文章上下架

今天任务比较水 主要是kafka入门和 文章上下架 以及异步通知article同步到app的前端数据 需要重新看一下&#xff08;使用步骤并不是很复杂 kafka主要解决高并发&#xff09; 1 kafka的入门 和 使用异步 需要重新看一下了流程和 详细信息 2 bug 打开app页面的时候出现503 服…

从0到1深入浅出构建Nest.Js项目

Nest (NestJS) 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。它利用JavaScript 的渐进增强的能力&#xff0c;使用并完全支持 TypeScript &#xff08;仍然允许开发者使用纯 JavaScript 进行开发&#xff09;&#xff0c;并结合了 OOP &#xff08;面向对…

动手学运动规划: 2.2.c 3次样条曲线代码解析

学习? 学个P!☺ — 亮剑 李云龙 &#x1f3f0;代码及环境配置&#xff1a;请参考 环境配置和代码运行! 本节提供了3次样条曲线的代码测试 python3 tests/curves/cubic_spline.py2.2.c.1 3次样条曲线代码实现 CubicSpline1D实现了1维的3次样条曲线, 需要输入一组离散点. Cub…

现在别买理想L7/L8,问界M8要来暴揍友商了

文 | AUTO芯球 作者 | 雷慢 问界又一重磅炸弹要来了&#xff0c; 它就是问界M8&#xff0c; 来看&#xff0c;M8刚又曝光了大量谍照。 现在我打听的消息是这样的&#xff0c; 11月广州车展亮相预售&#xff0c; 12月底正式上市&#xff0c;25年春节前后开始交付&#xff…

计算机网络:计算机网络体系结构 —— 专用术语总结

文章目录 专用术语实体协议服务服务访问点 SAP 服务原语 SP 协议数据单元 PDU服务数据单元 SDU 专用术语 实体 实体是指任何可以发送或接收信息的硬件或软件进程 对等实体是指通信双方处于相同层次中的实体&#xff0c;如通信双方应用层的浏览器进程和 Web 服务器进程。 协…

Java组件化开发:jar包

我在java基础&#xff1a;原始数据类型&#xff0c;包的创建与导入-CSDN博客一文中记录了包的使用&#xff0c;此文就详细讲解一下IDEA中如何进行组件化开发。 介绍 现在的软件系统功能越来越复杂&#xff0c;规模也越来越大&#xff0c;为了应对这种挑战&#xff0c;人们将“…

深入解析Python错误消息及解决方法

深入解析Python错误消息及解决方法 Python是开发者广泛使用的语言&#xff0c;因其简洁的语法和强大的标准库而深受欢迎。然而&#xff0c;Python程序在运行过程中&#xff0c;错误不可避免。理解Python的错误消息并正确处理这些错误&#xff0c;是提升代码质量和调试效率的重…

3.点位管理改造-列表查询——帝可得管理系统

目录 前言一、与页面原型差距1.现在&#xff1a;2.目标&#xff1a;3. 存在问题&#xff1a;所在区域和合作商ID展示的都是ID&#xff0c;而不是名称&#xff1b;同时合作商ID应改为合作商 二、修改1.重新设计SQL语句2.修改mapper层&#xff0c;使用Mybatis中的嵌套查询3.修改s…

AI人工智能人像修饰中文面板PS插件 Retouch Pro 3.2.0 中文汉化版

AI人工智能人像修饰PS扩展插件 Retouch Pro 3.2.0 中文汉化版 支持软件&#xff1a;PS 2018 – PS 2025或更高版本 系统要求&#xff1a;Windows系统 或 MacOS系统 出处&#xff1a;https://www.aeown.com/thread-3061-1-1.html Retouch Pro Panel 有一个非常强大和先进的人工…