柱状图中最大的矩形

news2025/1/11 8:16:21

题目链接

柱状图中最大的矩形

题目描述


注意点

解答思路

  • 暴力破解根据每根柱子x以x的高度作为矩形的高度找到其相邻能组成矩形的柱子,遍历所有柱子即可找到最大矩形,但是时间复杂度是O(n²),最终运行结果也超时了
  • 上面暴力破解的方法中大多数柱子都可能被遍历多次,这极大地降低了效率,所以考虑有没有一种方法遍历一次柱子即可,参照题解要想解决此题,只需要明确一点,遍历每个高度,是要以当前高度为基准,寻找最大的宽度,组成最大的矩形面积那就是要找左边第一个小于当前高度的下标left,再找右边第一个小于当前高度的下标right,那宽度就是这两个下标之间的距离了,用单调栈就可以很方便确定这两个边界了,单调栈其存储的是高度单调递增的柱子(也有相等的情况,放在后续考虑),且存储的是柱子的坐标(方便确定边界)。
  • 在遍历到某个柱子k相比于栈顶柱子j的高度低时,此时就已经找到了栈顶柱子j左右两侧第一个小于j的高度的柱子坐标,也就可以确定栈顶柱子j作为高度的矩形最大面积,边界也就是柱子i和k的坐标之间的距离,确定了柱子j作为高度的矩形最大面积后就可以将其在栈中排除掉,以此类推,便确定了多数柱子为高度的最大面积(注意只是确定了该柱子的高度作为矩形高度的最大矩形,其仍有可能只用高度的一部分与其他柱子共同组成面积更大的矩形,但是其是由后面的柱子所决定的),且保证了单调栈中的柱子高度是递增的
  • 在一次遍历后确定了多数柱子组成的最大矩形后,栈中还有可能剩有柱子(此时栈是单调递增的),需要对剩下柱子所能组成矩形的最大面积进行计算,此时高度就是栈顶柱子高度,右边界就是第一次弹出的栈顶柱子坐标(后续其余柱子的高度和右边界会有变化,但是右边界始终都是该坐标,因为后续柱子都肯定能与之前的柱子组成矩形),而左边界要分情况考虑:一是弹出栈顶柱子后此时栈中无柱子,则说明该柱子左侧所有的柱子都能与其组成矩形,左边界为0;二是弹出栈顶柱子后此时新的栈顶柱子与其高度相等,则其能与新的栈顶柱子组成矩形,以此类推,需要找到第一个与栈顶柱子高度不相同的柱子的坐标作为左边界;三是弹出栈顶柱子后此时新的栈顶柱子与其高度不相等,则新的栈顶柱子高度肯定低于其高度,无法组成矩形,左边界就是新的栈顶柱子坐标

代码

class Solution {
    public int largestRectangleArea(int[] heights) {
        int n = heights.length, res = 0;
        // 栈用于存储递增的柱子的坐标(只会单调递增,也有相等的情况,如果高度递减则会进行出栈相关操作)
        Deque<Integer> stk = new ArrayDeque<>();
        for (int i = 0; i < n; i++) {
            // 找到了递减的柱子k,则可以算出其前一个更高的柱子j作为高度的最大面积
            while (stk.size() != 0 && heights[stk.peek()] > heights[i]) {
                int idx = stk.pop();
                // 左边界为柱子j的前一个更低的柱子k,又因为栈只会单调递增,所以就是栈中相邻的柱子(注意考虑边界情况)
                int left = stk.size() != 0 ? stk.peek() : -1;
                int area = heights[idx] * (i - left - 1);
                res = Math.max(res, area);
            }
            stk.push(i);
        }
        if (stk.size() == 0) {
            return res;
        }
        // 栈不为空时对剩余单调递增且不确定最大面积的柱子进行计算
        int right = stk.peek();
        while (stk.size() != 0) {
            int idx = stk.pop();
            // 此时对栈中相邻且高度相等的柱子也要进行考虑,其能共同组成一个矩形
            while (stk.size() != 0 && heights[idx] == heights[stk.peek()]) {
                stk.pop();
            }
            int left = stk.size() != 0 ? stk.peek() : -1;
            int area = heights[idx] * (right - left);
            res = Math.max(res, area);
        }
        return res;
    }
}

关键点

  • 要想解决此题,只需要明确一点,遍历每个高度,是要以当前高度为基准,寻找最大的宽度,组成最大的矩形面积那就是要找左边第一个小于当前高度的下标left,再找右边第一个小于当前高度的下标right,那宽度就是这两个下标之间的距离了,用单调栈就可以很方便确定这两个边界了
  • 在第一次遍历只能计算出左右两侧都有比其高度更低的柱子的最大矩形面积,栈中剩余的柱子都说明右侧没有比其高度更低的柱子,所以还需要对栈中剩余的柱子组成的最大矩形面积进行计算,其右边界都是一样的(最初栈顶柱子的坐标),左边界则需要考虑边界及与其柱子高度相等的情况

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

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

相关文章

MKS SERVO4257D 闭环步进电机_系列4 MODBUS指令说明

第1部分 产品介绍 MKS SERVO 28D/35D/42D/57D 系列闭环步进电机是创客基地为满足市场需求而自主研发的一款产品。具备脉冲接口和RS485/CAN串行接口&#xff0c;支持MODBUS-RTU通讯协议&#xff0c;内置高效FOC矢量算法&#xff0c;采用高精度编码器&#xff0c;通过位置反馈&am…

基于Android的视频分享平台的设计与实现

基于Android的视频分享平台的设计与实现 摘 要 短视频平台是以特定群众为目标的差异化群体定位工具。其利用自身的便捷性可以实现视频的随时拍摄和随时上传&#xff0c;可以产生亚文化圈的萌芽。这种开放便利的特性在吸引了广大用户的同时&#xff0c;也在一定程度上解决了由…

C#面试题 2

七、AOP如何在代码层面实现&#xff1f; ①静态代理实现AOP&#xff0c;自己写代理对象&#xff1b; ②动态代理实现AOP&#xff0c;运行时动态生成一个代理对象。 静态代理的实现&#xff1a;①装饰器模式&#xff08;允许向一个现有的对象添加新的功能&#xff0c;同时又不…

Doris----Rollup表分析及案例实现

ROLLUP 在多维分析中是“上卷”的意思&#xff0c;即将数据按某种指定的粒度进行进一步聚合。 之前的聚合模型: 用户id数据插入时间城市年龄性别最后一次访问的时间该用户的总消费额该用户的最大停留时长该用户的最小停留时长100002017/10/2北京1002017/10/02 08:00:00651521…

C++:STL--List

文章目录 一.STL-list的数据结构链表结点模板 二.List的框架与迭代器的实现1.STL中的容器迭代器2.List的迭代器List正向遍历迭代器类模板(对ListNode< T >* 指针的封装)反向遍历迭代器的类模板(对正向迭代器的封装) 3.List的实现框架 三. List的成员接口的实现1.在List类…

GPT-4发布!ChatGPT大升级!太太太太强了!

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 我新建了人工智能中文站https://ai.weoknow.com 每天给大家更新可用的国内可用chatGPT资源 一觉醒来&#xff0c;万众期待的GPT-4&#xff0c;它来了&#xff01; OpenAI老板Sam Altman直接开门见山地介绍说&#xff1a…

C语言之数组指针2.0

在 C 语言中&#xff0c;数组指针是一种特殊的指针类型&#xff0c;它是一个指向数组的指针。其声明形式为&#xff1a; <数据类型> (*<指针变量名>)[<数组长度>];例如&#xff0c;下面声明了一个指向整型数组的指针变量 arrPtr&#xff1a; int (*arrPtr)…

数据等级划分

数据大致可以分为定性数据与定量数据&#xff0c;但细分可以分为四类&#xff1a;定类数据、定序数据、定距数据、定比数据 处理数据的流程&#xff1a; 参考&#xff1a; 特征工程入门与实践

如何使用ChatGPT提升自己的“码”力?

如何使用chatGPT提升自己的"码"力? 代码评审(CodeReview)代码优化代码释义提供解决方案代码生成设计模式和架构建议学习新知识总结 ChatGPT是什么&#xff0c;我就不用再多介绍了吧&#xff01;相信大家已经看到了它在文本领域所展现出来的实力&#xff0c;虽然目前…

PAT A1152 Google Recruitment

1152 Google Recruitment 分数 20 作者 陈越 单位 浙江大学 In July 2004, Google posted on a giant billboard along Highway 101 in Silicon Valley (shown in the picture below) for recruitment. The content is super-simple, a URL consisting of the first 10-dig…

2023商家外卖数据

商家列表 外卖商品销量 shop_channel varchar(20) DEFAULT NULL, shop_system varchar(20) DEFAULT NULL, shop_system_no varchar(50) DEFAULT NULL, shop_platform varchar(20) DEFAULT NULL, shop_id varchar(50) NOT NULL, shop_id_str varchar(50) NO…

ChatGPT自动生成思维导图

&#x1f34f;&#x1f350;&#x1f34a;&#x1f351;&#x1f352;&#x1f353;&#x1fad0;&#x1f951;&#x1f34b;&#x1f349; ChatGPT自动生成思维导图 文章目录 &#x1f350;问题引入&#x1f350;具体操作markmapXmind &#x1f433;结语 &#x1f…

【Web】JWT(JSON Web Token)验证是什么?和SWT,SMAL的区别

JWT是什么&#xff1f; JWT&#xff08;JSON Web Token&#xff09;是一种轻量级的安全传输方式&#xff0c;可以用于在不同的系统之间传递安全可靠的信息&#xff0c;例如用户身份验证、授权和信息交换等。JWT采用JSON格式对信息进行编码和传输&#xff0c;用于在各方之间以 …

SpringCloud:分布式缓存之Redis持久化

Redis有两种持久化方案&#xff1a; RDB持久化AOF持久化 1.RDB持久化 RDB全称Redis Database Backup file&#xff08;Redis数据备份文件&#xff09;&#xff0c;也被叫做Redis数据快照。简单来说就是把内存中的所有数据都记录到磁盘中。当Redis实例故障重启后&#xff0c;…

如何安装389目录服务器作为CentOS 8 / RHEL 8机器的LDAP服务器?

LDAP&#xff08;轻量级目录访问协议&#xff09;是一种用于访问和维护分布式目录服务的开放标准协议。 389目录服务器是一个功能强大、高性能的LDAP服务器&#xff0c;它可以用于存储和管理用户、组和其他网络对象的身份验证和授权信息。本文将详细介绍如何在CentOS 8 / RHEL…

学生成绩管理系统

基于springboot vue实现的学生成绩管理系统 主要模块&#xff1a; 1&#xff09;学生模块&#xff1a;我的成绩、成绩统计、申述管理、修改密码 2&#xff09;教师模块&#xff1a;任务管理、对学生班级任务安排、班级学生的成绩查看、申述管理 3&#xff09;管理员模块&…

(可直接使用)在线语音识别APP+阿里云平台+Android Studio 开发项目

目录 所以需要下载软件 (1)Android Studio (2)夜神模拟器 1&#xff1a;在阿里云平台中&#xff0c;登录账号&#xff0c;选择控制台&#xff0c;搜索 智能语音交互 2&#xff1a;智能语音交互 界面 3:创建项目 4&#xff1a;选择项目类别 可以选择 语音识别语…

C++初识仿函数

C初识仿函数 &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容简单介绍了仿函数的概念 文章目录 C初识仿函数…

计算机组成原理-中央处理器-CPU指令和数据执行过程

目录 一、CPU的功能和基本架构 二、指令cpu执行过程 指令周期​编辑 各周期执行过程 指令执行方案 三、数据通路 3.1 cpu内部单总线 3.1.1 寄存器之间传送 3.1.2 主存与cpu之间数据传送 3.1.3 执行算术或逻辑运算的 3.2 cpu内部多总线 3.3 专用数据通路 一、CPU的功能和…

javascript基础九:说说Javascript中的继承?如何实现继承?

一、是什么 继承&#xff08;inheritance&#xff09;是面向对象软件技术当中的一个概念 如果一个类别B“继承自”另一个类别A&#xff0c;就把这个B称为“A的子类”&#xff0c;而把A称为“B的父类别”也可以称“A是B的超类” 继承的优点 继承可以使得子类具有父类别的各种属性…