【算法练习Day51】柱状图中最大的矩形

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:练题
🎯长路漫漫浩浩,万事皆有期待

文章目录

  • 柱状图中最大的矩形
    • 思路
    • 动态规划
    • 单调栈
  • 总结:

柱状图中最大的矩形

力扣题目链接

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

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

示例 1:

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

示例 2:

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

思路

接雨水 中是找每个柱子左右两边第一个大于该柱子高度的柱子,而本题是找每个柱子左右两边第一个小于该柱子的柱子。

为什么这么说呢,因为如下图所示,高为3的柱子可以继续往右边蔓延扩大面积,如果往左边的话则长度不够
在这里插入图片描述

所以要找当前柱子i左右两侧第一个小于他的柱子

动态规划

对于下标i而言,能勾勒出的最大面积是什么?

以i为中心, 向左寻找第一个小于height[i]的下标minLeftIndex, 向右寻找第一个小于height[i]的下标minRightIndex, 即最大面积 = height[i] * (minRightIndex - minLeftIndex - 1)

如示例1中,求i=4的最大面积
在这里插入图片描述

正向遍历数组 height 得到数组 minLeftIndex的每个索引值(第一小于当前柱子高度的索引值),反向遍历数组 height 得到数组minRightIndex(第一小于当前柱子高度的索引值)

完整代码:

public int largestRectangleArea(int[] heights) {
    int[] minLeftIndex = new int[heights.length];
    int[] minRightIndex = new int[heights.length];

    // 记录每个柱子 左边第一个小于该柱子的下标
    minLeftIndex[0] = -1;
    for (int i = 1; i < heights.length; i++) {
        int left = i - 1;
        // 这里不是用if,而是不断向左寻找的过程
        while (left >= 0 && heights[left] >= heights[i]) {
            left = minLeftIndex[left];
        }
        minLeftIndex[i] = left;
    }

    // 记录每个柱子 右边第一个小于该柱子的下标
    minRightIndex[heights.length - 1] = heights.length;
    for (int i = heights.length - 2; i >= 0; i--) {
        int right = i + 1;
        // 这里不是用if,而是不断向右寻找的过程
        while (right < heights.length && heights[right] >= heights[i]) {
            right = minRightIndex[right];
        }
        minRightIndex[i] = right;
    }

    // 求和
    int res = 0;
    for (int i = 0; i < heights.length; i++) {
        int sum = heights[i] * (minRightIndex[i] - minLeftIndex[i] - 1);
        res = Math.max(sum, res);
    }
    return res;
}

单调栈

本题是找每个柱子左右两边第一个小于该柱的柱子。这里就涉及到了单调栈很重要的性质,就是单调栈里的顺序,是从小到大还是从大到小。

在题解 接雨水 中接雨水的单调栈从栈头(元素从栈顶弹出)到栈底的顺序应该是从小到大的顺序。

那么因为本题是要找每个柱子左右两边第一个小于该柱子的柱子,所以从栈顶到栈底的顺序应该是从大到小的顺序!

如图所示的例子
在这里插入图片描述

当我们遍历到height[5]时,因为栈顶到栈底是从大到小,height[5]高度是小于栈顶元素的,所以就找到了此时的栈顶元素的左右第一个小于的柱子

在这里插入图片描述

此时大家应该可以发现其实就是栈顶和栈顶的下一个元素以及要入栈的三个元素组成了我们要求最大面积的高度和宽度

剩下就是分析清楚如下三种情况:

情况一:当前遍历的元素heights[i]小于栈顶元素heights[st.top()]的情况
情况二:当前遍历的元素heights[i]等于栈顶元素heights[st.top()]的情况
情况三:当前遍历的元素heights[i]大于栈顶元素heights[st.top()]的情况
完整代码:

public int largestRectangleArea(int[] heights) {
    Deque<Integer> stack = new LinkedList<>();
    // 数组扩容,在头和尾各加入一个元素
    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];
    }

    // 之后就用newHeights计算
    stack.push(0);
    int res = 0;
    // 第一个元素已经入栈,从下标1开始
    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 {
            // 我们要找到一个不小于newHeights[i]为止
            while (newHeights[i] < newHeights[stack.peek()]) {
                int mid = stack.peek(); // 中间柱子
                stack.pop();
                int left = stack.peek();
                int right = i;
                int w = right - left - 1;
                int h = newHeights[mid];
                res = Math.max(res, w * h);
            }
            stack.push(i);
        }
    }

    return res;
}

总结:

今天我们完成了柱状图中最大的矩形这道题,相关的思想需要多复习回顾。接下来,我们继续进行算法练习。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTML+CSS:飞翔按钮

效果演示 实现了一个按钮的动画效果&#xff0c;当鼠标悬停在按钮上时&#xff0c;按钮的背景颜色和图标会发生变化&#xff0c;并且图标会旋转45度并向右移动1.2em&#xff0c;同时按钮中的文字也会向右移动5em。当鼠标点击按钮时&#xff0c;按钮会变小并向下移动0.1em。整个…

软考复习之软件工程篇

软件生命周期 问题定义&#xff1a;要示系统分析员与用户进行交流&#xff0c;弄清”用户需要计算机解决什么问题”然后提出关于“系统目标与范围的说明”&#xff0c;提交用户审查和确认 可行性研究&#xff1a;一方面在于把待开发的系统的目标以明确的语言描述出来&#xf…

LINUX服务之YUM仓库

1. YUM概述 YUM基于RPM包构建的软件更新机制 可以自动解决依赖关系 所有软件包由集中的YUM软件仓库提供 YUM支持软件源 搭建yum支持的的软件源主要有以下三种&#xff1a; 本地yum&#xff1a;file&#xff1a;//… 网络yum&#xff0c;又分为HTTP服务器&#xff1a;http…

Vue3 watch与watchEffect区别

✨ 专栏介绍 在当今Web开发领域中&#xff0c;构建交互性强、可复用且易于维护的用户界面是至关重要的。而Vue.js作为一款现代化且流行的JavaScript框架&#xff0c;正是为了满足这些需求而诞生。它采用了MVVM架构模式&#xff0c;并通过数据驱动和组件化的方式&#xff0c;使…

从全流程的角度来了解python包的使用,也许你会有不一样的认识

在python中&#xff0c;只要我们一谈到包或模块&#xff0c;基本默认说的就是包的导入和使用。也就是说只要我们知道包的名字&#xff0c;导入后知道怎么使用基本就可以了&#xff0c;但本人认为&#xff0c;我们仅仅了解的是包的一部分&#xff0c;若想对包有个整体的认识&…

376. 摆动序列 - 力扣(LeetCode)

题目描述 如果连续数字之间的差严格地在正数和负数之间交替&#xff0c;则数字序列称为摆动序列。第一个差&#xff08;如果存在的话&#xff09;可能是正数或负数。少于两个元素的序列也是摆动序列。 例如&#xff0c; [1,7,4,9,2,5] 是一个摆动序列&#xff0c;因为差值 (6,…

【机器学习300问】15、什么是逻辑回归模型?

一、逻辑回归模型是为了解决什么问题&#xff1f; 逻辑回归&#xff08;Logistic Regression&#xff09;是一种广义线性回归分析模型&#xff0c;尤其适用于解决二分类问题&#xff08;输出为两个类别&#xff09;。 &#xff08;1&#xff09;二分类举例 邮件过滤&#xff…

详解BLDC和PMSM的特点

文章目录 前言BLDC和PMSM的优点基础架构前言 在电机领域中,有刷电机和无刷电机代表着两种不同的技术路径。有刷电机的绕组通常位于转子,即电机的旋转部分。 而无刷电机则采用一种更为先进的设计,其绕组安置在定子,即电机的静止部分。 这样的设计理念在于将绕组固定在电机的…

深入理解stress/stress-ng

文章目录 一、概述二、安装2.1、源码编译安装2.2、命令行安装2.3、安装确认 三、重要参数详解3.1、查询支持的参数3.2、重要参数说明 四、实例4.1、压测CPU4.2、压测内存4.3、压测IO4.4、压测磁盘及IO4.5、压测磁盘及CPU 团队博客: 汽车电子社区 一、概述 stress是一种工作负载…

【AIGC】Diffusers:AutoPipeline自动化扩散生图管道

前言 &#x1f917; 扩散器能够完成许多不同的任务&#xff0c;并且您通常可以将相同的预训练权重用于多个任务&#xff0c;例如文本到图像、图像到图像和修复。但是&#xff0c;如果您不熟悉库和扩散模型&#xff0c;可能很难知道将哪个管道用于任务。例如&#xff0c;如果您…

新闻界的AI革命:Newspager GPT 全面解析

简介有没有想过一家报社是如何运作的&#xff1f;传统的报社要有策划、采编、编辑、美工、审校等等角色&#xff0c;而现在借助 AI&#xff0c;很多事情可以由 AI 代替了&#xff01;Newspager GPT 就是这样一个由多智能体组成的 AI 系统&#xff0c;你只要输入几个你感兴趣的主…

Javaweb之SpringBootWeb案例之阿里云OSS服务入门的详细解析

2.3.2 入门 阿里云oss 对象存储服务的准备工作我们已经完成了&#xff0c;接下来我们就来完成第二步操作&#xff1a;参照官方所提供的sdk示例来编写入门程序。 首先我们需要来打开阿里云OSS的官方文档&#xff0c;在官方文档中找到 SDK 的示例代码&#xff1a; 参照官方提供…

基于 Gurobi 的纸浆运载船顺序装卸决策建模求解|Gurobi优化应用

Pulp-Carrier-Loading-Optimization-with-Gurobi 基于 Gurobi 的纸浆运载船顺序装卸决策建模求解。中山大学智能工程学院《运筹学》课程期末建模课程设计。优化工具&#xff1a;Python的Gurobi 项目仓库 Github: Pulp-Carrier-Loading-Optimization-with-Gurobi 摘要 本研究…

E4 基于Mysql的游标定义和应用

一、实验目的: 熟练使用MySQL游标的定义和应用。 二、实验要求: 1、基本硬件配置:英特尔Pentium III 以上,大于4G内存&#xff1b; 2、软件要求:Mysql&#xff1b; 3、时间:1小时&#xff1b; 4、撰写实验报告并按时提交。 三、实验内容: 问题1&#xff1a;请写一个存储…

快速打通 Vue 3(五):详解 Vue 中的路由

08. 路由 很激动进入了 Vue 3 的学习&#xff0c;作为一个已经上线了三年多的框架&#xff0c;很多项目都开始使用 Vue 3 来编写了 这一组文章主要聚焦于 Vue 3 的新技术和新特性 如果想要学习基础的 Vue 语法可以看我专栏中的其他博客 Vue&#xff08;一&#xff09;&#xff…

蓝桥杯备战——5.动态数码管扫描

1.分析原理图 经查阅说明书得知数码管为共阳极&#xff0c;共阳端口接到了U8,而段码接到了U7。 如果需要选中U8,我们只需要将P250;P261;P271; 如果需要选中U7,我们只需要将P251;P261;P271; 2.代码示例 void Delay1ms() //12.000MHz {unsigned char data i, j;i 12;j 169;…

贪心算法-01:跳跃游戏

关于贪心算法 贪心算法是动态规划的一个特例&#xff0c;相对于动态规划&#xff0c;使用贪心算法需要满足更多条件&#xff0c;但是效率比动态规划要高。 贪心选择的性质就是&#xff1a;每一步都做出一个局部最优解&#xff0c;最终的结果就是全局最优。不过这是一种特殊性…

uniapp组件库中Collapse 折叠面板 的使用方法

目录 #平台差异说明 #基本使用 #控制面板的初始状态&#xff0c;以及是否可以操作 #自定义样式 #1. 如果修改展开后的内容&#xff1f; #2. 如何自定义标题的样式&#xff1f; #3. 如何修改整个Item的样式&#xff1f; #API #Collapse Props #Collapse Item Props #…

ORM-06-jooq 入门介绍

拓展阅读 The jdbc pool for java.(java 手写 jdbc 数据库连接池实现) The simple mybatis.&#xff08;手写简易版 mybatis&#xff09; JOOQ JOOQ 可以通过数据库直接生成 java 代码&#xff0c;通过 flent-api 进行数据库操作。 SQL builder JOOQ 非常的灵活和强大。你可…

深入理解旅游网站开发:Java+SpringBoot+Vue+MySQL的实战经验

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…