当前位置: 首页 > news >正文

计算柱状图中最大的矩形【单调栈】

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例 1:
输入:heights = [2,1,5,6,2,3]
输出:10
示例 2:
输入: heights = [2,4]
输出: 4
LeetCode链接:https://leetcode.cn/problems/largest-rectangle-in-histogram/description/

暴力思路

        最先想到的也是最简单的思路,遍历列表计算每个高度的最大区域,但是无法在规定时间内处理105级别的数据。和常规的暴力解法不同,我先对列表中的元素进行了一轮排序,然后从大到小进行查找,同时跳过数值相同的元素,可以在一定程度上减少处理时间。

class Solution {
public:int largestRectangleArea(vector<int>& heights) {int maxArea = 0;int hSize = heights.size();int w = 0, _w = 0;// 辅助vector<int> tmp(heights);// 存储不同最大最小高度的面积vector<int> allArea = {};sort(tmp.begin(), tmp.end());allArea.push_back(tmp[0] * hSize);for (int i = 1; i < hSize; i++) {if (tmp[i] == tmp[i - 1])continue;int _j = -1;bool flag = false;for (int j = 0; j < hSize; j++) {// 从大于tmp[i]的地方开始if (tmp[i] <= heights[j]) {if (!flag) {_j = j;flag = true;}}// j 比当前小, 或者j到末尾if (flag && ((tmp[i] > heights[j]) || j == (hSize - 1))) {w = j - _j;if (j == (hSize - 1) && (tmp[i] <= heights[j]))w++;if (_w < w)_w = w;flag = false;}}//_w 为以tmp[i]做最小高度的最长区间allArea.push_back(tmp[i] * _w);_w = 0;}for (int i = 0; i < allArea.size(); i++) {// cout << allArea[i] << ' ';if (maxArea < allArea[i])maxArea = allArea[i];}return maxArea;}
};

提交后显示超出时间限制
OOT

单调栈思路

单调栈

        单调栈是对栈的一种使用方法并不是固定的数据结构,通过比较当前元素和栈顶元素之间的大小关系进行入栈、计算、出栈等操作,有单增栈和单减栈两种用法。本题使用的是单增栈。
求解最大矩形区域可以视作求解每个元素的最大区域,然后(或并)选取其中最大的。以输入[2,1,5,6,2,3]为例,求解过程为先计算第一个元素2的最大区域易得2,再计算第二个元素1的最大区域。。。直到最后一个元素,可以得到最大区域列表[2, 6, 10, 6, 8, 3]。最大区域由高度和宽度两方面组成,其中宽度由左右两端第一个小于当前元素的元素下标决定。可以通过在单调栈中存储单增序列的下标实现通过对数组的一次遍历,求得最大区域,达到*O(n)*的时间复杂度。以[2,1,5,6,2,3]为例,具体过程如下:

单调递增栈操作1、S1[栈状态] --> T1[0]2、T1 --2<1? 弹出0--> T2[]3、T2 --> 压入14、S2[:1] --5>1?--> 压入25、S3[:1,2] --6>5?--> 压入36、S4[:1,2,3] --2<6? 弹出3--> 计算6的最大区域7、S5[:1,2] --2<5? 弹出2--> 计算5的最大区域8、S6[:1] --2>1?--> 压入49、S7[:1,4] --3>2?--> 压入510、S8[:1,4,5] --0>3? 弹出5--> 计算3的最大区域11、S9[:1,4,5] --0>2? 弹出4--> 计算2的最大区域12、S10[:1,4,5] --0>1? 弹出1--> 计算1的最大区域end

        使用单调栈时,主要分两种操作:
1、入栈。当当前元素大于栈顶元素(或栈为空)时,将当前元素下标入栈。
2、出栈并计算最大区域。当栈不为空,且当前元素小于栈顶元素时,进行出栈操作,计算栈顶元素的区间,并比较存储区域面积。如果栈顶元素依旧大于当前元素,则继续进行计算,直到栈顶元素小于当前元素(步骤8),或栈为空(步骤2)。计算面积时,高度固定,宽度需要计算,此时存在两种情况,栈为空和栈不为空,其中:栈不为空时,l表示左侧小于当前元素的位置使用r-l-1;栈为空时表示左侧没有元素大于当前元素,此时区间的长度为当前r所在的位置,l的值为需为-1。当前l左侧不为空时,需要继续计算后续元素的最大区间,因此需要出栈栈顶元素,并进行新一轮比较,判断需要入栈还是出栈,最后的中止条件为遍历整个数组输入的元素。
此外,为了保证右侧有终止,需要在输入数组的尾部补0,用作右下界。

根据以上逻辑,可得以下代码:

class Solution {
public:int largestRectangleArea(vector<int>& heights) {int Res = 0;stack<int> length;heights.push_back(0);for (int r = 0; r < heights.size(); r++) {while (!length.empty() && heights[r] <= heights[length.top()]) {int h = heights[length.top()];length.pop();int l = length.empty() ? -1 : length.top();Res = max((r - l - 1) * h, Res);}length.push(r);}return Res;}
};

执行结果:
单调栈

http://www.dtcms.com/a/301342.html

相关文章:

  • Dify 本地化部署深度解析与实战指南
  • 蜣螂优化算法的华丽转身:基于Streamlit的MSIDBO算法可视化平台
  • 【ESP32设备通信】-W5500与ESP32 /ESP32 S3集成
  • MySQL - 性能优化
  • Java面试实战:电商高并发与分布式事务处理
  • maven optional 功能详解
  • Java进阶7:Junit单元测试
  • 数据结构基础内容(第九篇:最短路径)
  • OpenCv中的 KNN 算法实现手写数字的识别
  • 电子电路设计学习
  • git回退版本教程
  • Java validation
  • Java学习第八十部分——Freemarker
  • Linux c网络专栏第三章DPDK
  • Petalinux驱动开发
  • Linux驱动开发笔记(五)——设备树(下)——OF函数
  • 人社部物联网安装调试员的实训平台
  • RabbitMq 常用命令和REST API
  • 9.SpringBoot Web请求参数绑定方法
  • 盛最多水的容器-leetcode
  • 《Java 程序设计》第 7 章 - 继承与多态
  • 记录几个SystemVerilog的语法——时钟块和进程通信
  • maven聚合工程(多个mudule只编译、打包指定module)
  • JVM类加载机制全流程详解
  • 通过硬编码函数地址并转换为函数指针来调用函数
  • Java#包管理器来时的路
  • Leetcode-3427变长子数组求和
  • Mitk教程案例项目编译
  • 嵌入式——单片机的独立按键
  • 【3DsMax+Zbrush+SP】风格化低多边形模型制作教程——以制作杯子为例——03在Substance Painter中制作材质