力扣-84. 柱状图中最大的矩形

news/2024/11/19 5:33:47/文章来源:https://www.cnblogs.com/trmbh12/p/18197926

1.题目介绍

题目地址(84. 柱状图中最大的矩形 - 力扣(LeetCode))

https://leetcode.cn/problems/largest-rectangle-in-histogram/

题目描述

给定 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

2.题解

2.1 暴力枚举(枚举左边界-底边)

思路

这里我们枚举左边界和右边界的范围,这样我们也就确定了heights数组的遍历范围,从中根据木桶效应找到最小的高,面积=底边*高

代码

  • 语言支持:C++

C++ Code:

class Solution {
public:int largestRectangleArea(vector<int>& heights) {int n = heights.size();int ans = 0;// 枚举左边界for(int left = 0; left < n; left++){int h = heights[left];for(int right = left; right < n; right++){h = min(h, heights[right]);ans = max(ans, (right - left + 1) * h);}}return ans;}
};

复杂度分析

令 n 为数组长度。

  • 时间复杂度:\(O(n^2)\)
  • 空间复杂度:\(O(n)\)

2.2 暴力枚举(枚举高)

思路

我们首先笃定矩形的高为某个值,然后以这个高为中心,向两边进行中心扩展,知道遇到小于这个高的情况(这时候再加上这个小于的就与我们笃定的假设相驳)
这里需要注意一下,如果我们使用的是while循环,最后结束的情况是第一个不满足条件的left或right而不是最后一个满足条件的left或right,
所以这里两种处理方法,要不然后面使用left+1和right-1, 结果改为(right - 1 - left - 1 + 1) * height; 要不然while判断条件改为如下代码所示即可

代码

  • 语言支持:C++

C++ Code:

class Solution {
public:int largestRectangleArea(vector<int>& heights) {int n = heights.size();int ans = 0;// 枚举高for(int mid = 0; mid < n; mid++){int left = mid, right = mid;while(left-1 >= 0 && heights[left-1] >= heights[mid]){left--;}while(right+1 < n && heights[right+1] >= heights[mid]){right++;}ans = max(ans, (right - left + 1) * heights[mid]);}return ans;}
};

复杂度分析

令 n 为数组长度。

  • 时间复杂度:\(O(n^2)\)
  • 空间复杂度:\(O(n)\)

2.3 单调栈

思路

这里我们继续2.2中确定高的思路,从中间向两边扩展,我们要找到左边第一个小于该高的索引和右边第一个小于该高的索引
如果向2.2一样,我们每次先遍历到每个高,然后向四周进行扩展,这样最坏情况相当于我们每次都需要遍历一次整个heights数组
有没有办法我们事先知道每个高它左侧第一个更小高和右侧第一个更小高呢? 这里我们就思考使用单调栈来解决问题.

我们对于该heights数组进行事先处理.求出更小高并存储到两个数组中
首先对于左侧元素,我们从左侧开始遍历,这里有一个性质,如果出现一个高hi小于其左侧的hx,那么对于索引i右侧的所有元素,他们找更小高,只有可能找到hi或者更左侧的高,而不会找到hx,
因为 x < i < ..., 如果 hi < h... 那么就是hi; 如果 hi > h, 又因为 hi < hx, 所以 hx > hi > h..., 必然不可能是hx

我们考虑用一个单调栈来维护这些高(帮助我们快速找到更小高),
1.如果当前高小于等于栈顶高,说明从此处以后,该栈顶高不可能作为更小高存在,我们不需要进行判断,将其从栈中弹出即可;
2.如果当前高大于栈顶高,说明我们找到了最近更小高(由于栈先进后出的性质,栈顶的是我们最近压进去的),将其进行存储
3.将当前高进行存储,压入栈(整体栈还是单调栈)

注意一点,这里我们找到了最近更小高的索引,但是我们实际需要的不是最近更小高的索引(第一个不满足条件的高), 而是要的最后一个满足条件的高(边界)
即实际上是left + 1 和 right - 1, 但这里我们存的是 left 和 right, 所以最后(right - 1 - (left + 1) + 1) = (right - left - 1)为实际的底边
但是我们也可以在存储动动手脚, 改为'left[i] = stk.empty()? 0:stk.top() + 1;' 和 right[j] = stk.empty()? n - 1 :stk.top() - 1; 找到的就是边界了!

代码

class Solution {
public:int largestRectangleArea(vector<int>& heights) {int n = heights.size();stack<int> stk;vector<int> left(n), right(n);for(int i = 0; i < n; i++){int h = heights[i];while(!stk.empty() && h <= heights[stk.top()]){stk.pop();}left[i] = stk.empty()?-1:stk.top();stk.push(i);}stk = stack<int>();for(int j = n - 1; j >= 0; j--){int h = heights[j];while(!stk.empty() && h <= heights[stk.top()]){stk.pop();}right[j] = stk.empty()?n:stk.top();stk.push(j);}int ans = 0;for(int i = 0; i < n; i++){ans = max(ans, (right[i] - left[i] - 1) * heights[i]);}return ans;}
};

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LuckFox-pico 入门记录一:编译环境与GPIO

LuckFox RV1106 点灯 本文使用VMwave+ubuntu20.04虚拟机,并用CLion开发linux,简单记录一下配置过程; 1 虚拟机安装 拿到板子,首先是配置环境,虚拟机选择ubuntu20.04,安装教程随便搜一下就行,网络配置选择NAT就行,可以不选择桥接模式,其他没有什么注意事项。 比较难的一…

tinkphp 配置二級域名访问

1.路由配置Route::domain(admin, function () {//系统管理Route::rule(/system/saveSubscriber$, admin/system/saveSubscriber,POST); });2.nginx 配置文件listen 80; server_name xxx.com admin.xxx.com;3.tp项目public下创建 nginx.htaccess 文件location / {index …

P7448

problem & 双倍经验 低配版本 没有 Ynoi 标志性算法卡常,这点差评。拆解问题 定义 \(lst_i\) 为上一个和 \(i\) 号点相同的位置。 由于几个转移都差不多,我们以 \([l,r - 1]\) 扩展到 \([l,r]\) 为例。 我们知道答案会加上 \([lst_r,r]\) 中 新出现的 且 \(> a_r\) 的…

Games101-9 advanced rendering

Physically Based Rendering: From Theory to Implementation (pbr-book.org) advanced light transport 有/无偏的光线传播方法双向路径追踪这里主要的光照为间接光 --- 不是直接光源 --- 实现比较困难。使用马尔科夫链进行推测。优势: 对于光线复杂的情况来水,比较好。 劣势…

Games101-1 Linear Algebra

简单介绍和资源列表 https://sites.cs.ucsb.edu/~lingqi/teaching/games101.html 线代vector -- 向量表示 $\vec{a}$ and $\mathbf{a}$ and $\vec{AB} = B - A$ 指代方向 没有起始点 向量的长度$\left | \vec{a} \right |$ 单位向量 $\hat{a} = \vec{a} / \left | \vec{a} \ri…

Games101-2 transform

2D point = $(x,y,1)^T$ 2D vector = $(x,y,0)^T$ --- 平移不变性transform translationAffine transformner逆变换 就是逆矩阵 变换的组合 矩阵的乘法 变换的分解变换到中心 旋转 变换回原始位置三维3D 旋转view transformationmodel transform view transform projection tr…

es集群迁移操作

logstash迁移集群/home/secure/logstash-7.8.1/bin/logstash -f /home/secure/logstash-7.8.1/config/event0515.conf -f --debug -f 检查配置文件语法/home/secure/logstash-7.8.1/bin/logstash -f /home/secure/logstash-7.8.1/config/event0515.conf > /home/secure…

智慧园区可视化大屏设计

首先,让我们来了解一下什么是智慧园区可视化大屏。简单来说,它是一种将复杂的数据通过图形化的方式展示出来的技术。这种技术的出现,让我们可以更直观、更清晰地理解数据,从而做出更准确的决策。那么,为什么我们要讨论智慧园区可视化大屏设计呢?因为,它不仅仅是一种技术…

【Modbus】转发:Modbus通讯模拟仿真环境的搭建

文章目录一、概要二、所需工具介绍三、搭建虚拟仿真环境1.Modbus RTU虚拟仿真环境搭建1.1.虚拟串口工具(VSPD)使用1.2.虚拟从站工具(ModSim32)使用1.3.虚拟主站工具(Modscan32)使用1.4.更改虚拟从站工具(ModSim32)的Modbus寄存器的值1.5.更改虚拟主站工具(Modscan32)…

深度学习项目-MobileNetV2水果识别模型

本项目旨在研究利用深度学习模型进行水果图像分类的方法,具体包括两个主要任务:一是使用卷积神经网络(CNN)模型进行水果图片的分类,二是探索轻量级神经网络模型MobileNetV2在水果图像分类中的应用。FruitRecognition DeepLearning深度学习小项目,利用CNN和MobileNetV2搭建…

celery异步框架

celery 介绍 https://github.com/celery/celery/ https://docs.celeryq.dev/en/stable/celery是一个分布式异步任务框架,是一个灵活且可靠的,处理大量消息的分布式系统,可以在多个节点之间处理某个任务,是一个专注于实时处理的任务队列,支持任务调度,所以 celery 本质上是…

北航研究生算法期末复习整理

算法设计与分析 数据结构 二叉树 线索二叉树(Threaded Binary Tree) 利用二叉链表中空的指针域指出结点在某种遍历序列中的直接前驱或直接后继 指向前驱和后继的指针称为线索 实现不用栈的树深度优先遍历算法 二叉查找树(Binary Search Tree, BST) 左子树都更小,右子树都更大…