代码随想录算法训练营day60 | 84.柱状图中最大的矩形

news2024/11/18 17:53:59

代码随想录算法训练营day60 | 84.柱状图中最大的矩形

  • 84.柱状图中最大的矩形
    • 解法一:单调栈
    • 解法二:暴力双指针(会超时)
    • 解法三:优化双指针
  • 总结

最后一天打卡留念!


84.柱状图中最大的矩形

教程视频:https://www.bilibili.com/video/BV1Ns4y1o7uB
在这里插入图片描述
在这里插入图片描述
包含索引i中部分面积的最大矩形面积取决于该索引两侧第一个小于height[i]的值,以及这两个索引之间的距离。
因此本题需要找到索引两侧第一个小于height[i]的值,适合用单调栈来解决。

解法一:单调栈

因为本题是要找每个柱子左右两边第一个小于该柱子的柱子,从栈头(元素从栈头弹出)到栈底的顺序应该是从大到小的顺序!
栈顶决定了最大面积的高度,和栈顶的下一个元素以及要入栈的三个元素决定了最大面积的宽度。

分析清楚如下三种情况:
情况一:当前遍历的元素heights[i]大于栈顶元素heights[stack.peek()]的情况
情况二:当前遍历的元素heights[i]等于栈顶元素heights[stack.peek()]的情况
情况三:当前遍历的元素heights[i]小于栈顶元素heights[stack.peek()]的情况

【注意】
为了保证一定存在左边界,需要再数组开头加个0;
为了保证一定存在右边界,需要再数组末尾加个0,这样才能保证对每个数值都计算对应最大面积(即最后弹出所有元素)。

class Solution {
    public int largestRectangleArea(int[] heights) {
         // 数组扩容,在头和尾各加入一个元素0
        int [] newHeights = new int[heights.length + 2];
        newHeights[0] = 0;
        newHeights[newHeights.length - 1] = 0;
        for (int index = 0; index < heights.length; index++){
            newHeights[index + 1] = heights[index];
        }

        int result = 0;
        Deque<Integer> stack = new LinkedList<>();
        stack.push(0);
        for(int i=1;i<newHeights.length;i++){
            if(newHeights[i]>newHeights[stack.peek()]){
                stack.push(i);
            }else if(newHeights[i]==newHeights[stack.peek()]){
                stack.pop();
                stack.push(i);
            }else{
                while(!stack.isEmpty() && newHeights[i]<newHeights[stack.peek()]){
                    int mid = stack.pop();
                    if(!stack.isEmpty()){
                        int left = stack.peek();
                        result = Math.max(result, newHeights[mid]*(i-left-1));
                    }
                }
                stack.push(i);
            }
        }
        return result;
    }
}

//精简版
class Solution {
    public int largestRectangleArea(int[] heights) {
        int[] newHeight = new int[heights.length + 2];
        System.arraycopy(heights, 0, newHeight, 1, heights.length);
        newHeight[heights.length+1] = 0;
        newHeight[0] = 0;

        Stack<Integer> stack = new Stack<>();
        stack.push(0);

        int res = 0;
        for (int i = 1; i < newHeight.length; i++) {
            while (newHeight[i] < newHeight[stack.peek()]) {
                int mid = stack.pop();
                int w = i - stack.peek() - 1;
                int h = newHeight[mid];
                res = Math.max(res, w * h);
            }
            stack.push(i);

        }
        return res;
    }
}

解法二:暴力双指针(会超时)

class Solution {
    public int largestRectangleArea(int[] heights) {
        int result=0;
         for(int i=0;i<heights.length;i++){
            int left=i-1;
            while(left>=0){
                if(heights[left]>heights[i])continue;
                left--;
            }
            if(left==-1)left=0;
            
            int right=i+1;
            while(right<heights.length){
                if(heights[right]>heights[i])continue;
                right++;
            }
            if(right==heights.length)right=heights.length-1;
            result=Math.max(result, (right-left-1)*heights[i]);
         }
         return result;
    }
}

解法三:优化双指针

class Solution {
    public int largestRectangleArea(int[] heights) {
        int length = heights.length;
        int[] leftMin = new int[length];
        int[] rightMin = new int[length];
        // 记录左边第一个小于该柱子的下标
        leftMin[0] = -1 ;
        for(int i=1;i<length;i++){
            int temp=i-1;
            while(temp>=0 && heights[temp]>=heights[i]){// 这里不断向左寻找的过程
                temp=leftMin[temp];
            }
            leftMin[i]=temp;
        }
        // 记录每个柱子右边第一个小于该柱子的下标
        rightMin[length-1]=length;
        for(int i=length-2;i>=0;i--){
            int temp=i+1;
            while(temp<length && heights[temp]>=heights[i]){// 这里不断向左寻找的过程
                temp=rightMin[temp];
            }
            rightMin[i]=temp;
        }
         // 求和
        int result = 0;
        for (int i = 0; i < length; i++) {
            int sum = heights[i] * (rightMin[i] - leftMin[i] - 1);
            result = Math.max(sum, result);
        }
        return result;
    }
}

总结

单调栈首先需要考虑栈内是递增还是递减,找左右第一个大于当前的元素用递增,找小于的用递减。
第二步是考虑要入栈的元素、栈顶元素三种关系下的处理逻辑。
如果要求两侧元素的话还需要考虑栈顶下一个元素,同时需要考虑首尾加0来处理边界问题。

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

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

相关文章

国产化麒麟linux系统QtCreator和QtCreator编译的程序无法输入中文libfcitx最新版本编译1.2.7

1.问题描述 麒麟linux系统QtCreator和QtCreator编译的程序无法输入中文&#xff0c;网上找了很多的libfcitxplatforminputcontextplugin.so库都无法使用正常输入&#xff1b; Qt版本&#xff1a;5.9.6 麒麟系统版本&#xff1a;海光麒麟桌面版kylin V10 SP1 小版本号2203 X…

一个多功能(聚合)查询接口,实现模糊、分页、主键、排序以及多条件查询

一个多功能(聚合)查询接口&#xff0c;实现模糊、分页、主键、排序以及多条件查询 前言 写的啰嗦了点&#xff0c;看效果请直接忽略中间&#xff0c;直接看后半部分。 引个流&#xff0c;公众号&#xff1a;小简聊开发 概念 瞎编的名字&#xff0c;哈哈哈&#xff0c;我就勉强…

一道北大强基题背后的故事(二)——出题者怎么想的?

早点关注我&#xff0c;精彩不错过&#xff01; 上篇文章中&#xff0c;我们给出一道北大强基考试中的试题&#xff0c;计算[((1 sqrt(5)) / 2) ^ 12]&#xff0c;给出了一条没有任何数学直觉&#xff0c;纯硬算的弯路以及题目的参考答案&#xff0c;相关内容请戳&#xff1a;…

IronPDF 2023.6.10 FOR NET CRACK

适用于.NET的IronPDF 2023.6.10 添加新的注释API并改进图像压缩逻辑。 2023年6月2日-14:42新版 特点 添加了新的连续进给选项。例如用于生成收据文档。 添加了新的注释API&#xff0c;包括注释删除。 添加了删除书签的功能。 将内存使用率和性能提高了10%。 改进了图像…

全球加速AEB「强标」,15万元以下车型或将「释放」巨量需求

目前&#xff0c;智能驾驶技术升级&#xff0c;主要是在帮助中高端车型提升产品竞争力&#xff0c;同时为车企构建未来软件付费盈利模式的转型。 但另一方面&#xff0c;基础辅助驾驶&#xff0c;尤其主动安全&#xff0c;比如&#xff0c;AEB&#xff08;自动紧急制动&#xf…

【企业化架构部署】基于Apache搭建LAMP架构

文章目录 前言一、LMAP架构介绍1.概念2.LAMP构建顺序3.LAMP编译安装4.各组件介绍4.1 Linux4.2 Apache4.3 MySQL4.4 PHP/Perl/Python 二、服务器部署1.Apache部署2.MySQL部署3.PHP部署4.安装论坛 前言 LAMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整…

考上大学,走进网安

出品&#xff5c;MS08067实验室&#xff08;www.ms08067.com&#xff09; 本文作者&#xff1a;北平靴 01 我和网络安全的相遇&#xff0c;说来很巧。2022年我考入吉林大学计算机学院&#xff0c;正巧我们的导助是学校ctf战队的成员&#xff0c;所以在刚入学的很清闲的日子里&a…

Python中logger模块的使用教程

参考模块&#xff1a; https://www.digitalocean.com/community/tutorials/how-to-use-logging-in-python-3 logger是python的内置模块&#xff0c;用以输出代码运行过程中的运行情况&#xff0c;极大的方便了我们的debug过程。参考资料中列出了使用logger相比于print优越的地方…

ResNet学习

目录 是什么作用怎么做论文阅读 视频来源&#xff1a;https://www.bilibili.com/video/BV1rZ4y1m7d9/?spm_id_from333.337.search-card.all.click&vd_sourcea402747bd6c153bdb2defee02a9cb617 https://www.bilibili.com/video/BV1rZ4y1m7d9/?spm_id_from333.788&vd_…

Java官方笔记5数字和字符串

Numbers Number的子类&#xff1a; 另外还有BigDecimal和BigInteger&#xff0c;用于高精度计算&#xff0c;AtomicInteger和AtomicLong用于多线程应用。 我们有时候需要用包装类而非基本数据类型&#xff0c;理由如下&#xff1a; 方法入参类型为Object&#xff0c;只能传入对…

什么是Linux shell

一句话概括&#xff1a;简单来说脚本就是将需要执行的命令保存到文本中&#xff0c;按照顺序执行&#xff08;由上往下执行&#xff09;&#xff0c;shell脚本:shell脚本就是一些命令的集合。 一、创建第一个Shell脚本&#xff1a;输出helloworld 1&#xff0e;脚本格式 脚本…

体验管理|“以旧换新”重塑“家电和耐用品”低频的消费需求

Guofu 第 96⭐️ 篇原创文章分享 &#xff08;点击&#x1f446;&#x1f3fb;上方卡片关注我&#xff0c;加⭐️星标⭐️~&#xff09; &#x1f68f; 写在前面 消费者越来越注重产品或服务的体验&#xff0c;而品牌也在竭力提供更好的体验来吸引和保留消费者。 &#x1f926;…

华为OD机试真题 Java 实现【火车进站】【牛客练习题】

一、题目描述 给定一个正整数N代表火车数量&#xff0c;0<N<10&#xff0c;接下来输入火车入站的序列&#xff0c;一共N辆火车&#xff0c;每辆火车以数字1-9编号&#xff0c;火车站只有一个方向进出&#xff0c;同时停靠在火车站的列车中&#xff0c;只有后进站的出站了…

基于SpringBoot+Vue的小区物业管理系统设计与实现

博主介绍&#xff1a; 大家好&#xff0c;我是一名在Java圈混迹十余年的程序员&#xff0c;精通Java编程语言&#xff0c;同时也熟练掌握微信小程序、Python和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我擅长在JavaWeb、SSH、SSM、SpringBoot等框架下…

【Android】拾物App期末作业

一、期末作业题目 《校园失物/拾物APP》 二、实施目的 通过本实训&#xff0c;使受训者可以深入理解Android相关技术&#xff0c;并将所学知识应用到实际的中等规模的程序设计中。同时&#xff0c;通过本实训&#xff0c;受训者可以拓展Android相关的知识&#xff0c;提升受训者…

修改EMC VNX的管理口IP地址

本文详细介绍如何修改EMC VNX存储的管理口的IP地址&#xff0c;注意Unifed 和block的VNX存储方法是有所不同的&#xff0c;这也是有好几个朋友问我这个问题&#xff0c;写这篇博客的原因。 在修改管理口的IP地址之前&#xff0c;要确保存储不在storage domain中&#xff0c;如…

MTK 人像双摄虚化导通流程

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、 创建 LogicalCameraName 相关的metadata二、 导通 LogicalCameraName Middleware 相关配置三、认 LogicalCameraName 是否创建成功四、双摄bringu…

用自然语言分割一切图像【lang-segment-anything】

近年来&#xff0c;计算机视觉取得了显着进步&#xff0c;特别是在图像分割和目标检测任务方面。 Segment Anything Model (SAM) 是最近的一项重大突破&#xff0c;这是一种多功能的深度学习模型&#xff0c;旨在有效地从图像和输入提示中预测对象掩码。 通过利用强大的编码器和…

听说最近AI应用爆了?!来AI Studio玩转大模型应用

‍ 飞桨 AI Studio 是基于百度深度学习平台飞桨&#xff08;PaddlePaddle&#xff09;的人工智能学习与实训社区&#xff0c;支持一站式模型在线开发与应用。提供优质开源模型、丰富的开源内容、功能强大的在线编程环境、云端超强 GPU 算力及存储资源&#xff0c;帮助开发者们快…

Docker镜像更新通知器DIUN

什么是 DIUN ? Docker Image Update Notifier 是一个用 Go 编写的 CLI 应用程序&#xff0c;可作为单个可执行文件和 Docker 映像交付&#xff0c;用于当 Docker 映像在 Docker registry中更新时接收通知。 和老苏之前介绍过的 watchtower 不同&#xff0c;DIUN 只是通知&…