题目:84. 柱状图中最大的矩形

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

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

示例:

输入: [2,1,5,6,2,3]

输出: 10




我们要求的是能勾勒出来的最大矩形面积

先用暴力破解整理一下思路,可以这样来做,循环遍历每根柱子,以每根柱子为高,不断向两边扩散直到遇到高度比自己低的柱子为止,求出最大面积

//核心代码如下
//从左往右遍历每根柱子
for (int i = 0; i < heights.length; i++) {
int w = 1;
int j = i - 1;
//向左扩散,直到遇到比自己高度低的柱子,宽度不断加一
while (j >= 0) {
if (heights[j] < heights[i]) {
break;
}else {
w++;
j--;
}
}
j = i + 1;
//向右遍历,直到遇到比自己低的柱子,宽度继续增加
while (j < heights.length) {
if (heights[j] < heights[i]) {
break;
}else {
w++;
j++;
}
}
//计算出来以这根柱子为高所能勾勒出来的面积,再比较赋值
maxArea = Math.max(maxArea,heights[i] * w);
}

每根柱子都会向左向右扩散,这样就造成了很多的重复,时间复杂度为O(N²),会超时

这时候再想能不能优化一下,使用更少的时间来解决问题

当使用暴力破解的时候,我们从左往右遍历每一根柱子进行求值

  因为柱子是从左边开始遍历过来的,所以遍历到某值时它左边的所有柱子的高度其实已经被遍历过了,所以我们可以用一个有序的栈来存储左边柱子的值,在这里我们使用递增的栈来存储左边元素

  当我们遍历到比栈顶元素高度更低的柱子时(反之,则入栈),说明以当前高度已经无法向右边扩撒了,而因为栈中元素是递增的,所以左边能扩散到的宽度就是到栈中的上一个元素 (先忽略柱子高度相等的情况),那么栈顶元素所能勾勒出来的最大矩形面积就可以求出来了


我们通过代码来进一步理解

class Solution {
public int largestRectangleArea(int[] heights) {
// 使用栈解决
// 注意:栈里面存储的是下标值,因为高度可以由下标值得出
int res = 0;
int len = heights.length;
Deque<Integer> stack = new ArrayDeque<>(); // 从左往右遍历每一根柱子
for (int i = 0; i < len; i++) {
// 当此时栈顶元素对应柱子的高度大于正在遍历的柱子高度时,进入循环
while (!stack.isEmpty() && heights[stack.peekLast()] > heights[i]) {
// 得出栈顶柱子的高度,并且将起弹出栈
int h = heights[stack.pollLast()]; // 特殊情况,如果现在栈顶柱子的高度与刚弹出栈的柱子的高度相等,那么将其弹出栈
while (!stack.isEmpty() && heights[stack.peekLast()] == h) {
stack.removeLast();
} // w 是所求柱子的宽度,如果栈不为空,它就等于 i 的值减去现在栈顶的值再减一
int w = 0;
if (stack.isEmpty()){
w = i;
} else {
w = i - stack.peekLast() - 1;
}
res = Math.max(res, h * w);
}
stack.addLast(i);
} // 此时栈中可能仍有元素,我们需要计算出以每根柱子为高能勾勒出最大的矩形面积,所以需要将所有元素都弹出栈
while (!stack.isEmpty()) {
int h = heights[stack.pollLast()];
int w = 0;
if (stack.isEmpty()) {
w = len;
} else {
w = len - stack.peekLast() - 1;
}
res = Math.max(res, h * w);
}
return res;
}
}

此时本题已经完成,但我们仍然可以继续进行优化---加入哨兵

比如说 [2,1,5,6,2,3] 是我们要求的柱状图,我们可以在数组的两端都插入 0 ,也就是在原先柱状图的基础上,在两端插入分别插入一个高度为0的柱子,变成[0,2,1,5,6,2,3,0],这样 0 就成为了最小的高度,那么遍历元素结束的时候,所有元素都可以弹出栈,就不用再考虑遍历完栈不为空的情况了

代码:

class Solution {
public int largestRectangleArea(int[] heights) {
// 加入哨兵进行优化
int res = 0;
int len = heights.length;
int[] newHeights = new int[len+2];
newHeights[0] = 0;
System.arraycopy(heights,0,newHeights,1,len);
heights = newHeights;
Deque<Integer> stack = new ArrayDeque<>();
stack.addLast(newHeights[0]);
len = len + 2;
for (int i = 1; i < len; i++) {
while (heights[i] < heights[stack.peekLast()]) {
int h = heights[stack.pollLast()];
int w = i - stack.peekLast() - 1;
res = Math.max(res, h * w);
}
stack.addLast(i);
}
return res;
}
}

LeetCode---84. 柱状图中最大的矩形(hard)的更多相关文章

  1. LeetCode 84. 柱状图中最大的矩形(Largest Rectangle in Histogram)

    84. 柱状图中最大的矩形 84. Largest Rectangle in Histogram

  2. Java实现 LeetCode 84 柱状图中最大得矩形

    84. 柱状图中最大的矩形 给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . 求在该柱状图中,能够勾勒出来的矩形的最大面积. 以上是柱状图的示例,其中每个柱子的 ...

  3. LeetCode 84. 柱状图中最大的矩形(Largest Rectangle in Histogram)

    题目描述 给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . 求在该柱状图中,能够勾勒出来的矩形的最大面积. 以上是柱状图的示例,其中每个柱子的宽度为 1,给定的 ...

  4. leetcode 84. 柱状图中最大的矩形 JAVA

    题目: 给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . 求在该柱状图中,能够勾勒出来的矩形的最大面积. 以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高 ...

  5. [LeetCode] 84. 柱状图中最大的矩形

    题目链接 : https://leetcode-cn.com/problems/largest-rectangle-in-histogram/ 题目描述: 给定 n 个非负整数,用来表示柱状图中各个柱 ...

  6. Leetcode84. 柱状图中最大的矩形(单调栈)

    84. 柱状图中最大的矩形 前置 单调栈 做法 连续区间组成的矩形,是看最短的那一块,求出每一块左边第一个小于其高度的位置,右边也同理,此块作为最短限制.需要两次单调栈 单调栈维护递增区间,每次不满足 ...

  7. 【LeetCode】84. Largest Rectangle in Histogram 柱状图中最大的矩形(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 单调栈 日期 题目地址: https://leetc ...

  8. LeetCode 84. Largest Rectangle in Histogram 单调栈应用

    LeetCode 84. Largest Rectangle in Histogram 单调栈应用 leetcode+ 循环数组,求右边第一个大的数字 求一个数组中右边第一个比他大的数(单调栈 Lee ...

  9. LeetCode(84): 柱状图中最大的矩形

    Hard! 题目描述: 给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . 求在该柱状图中,能够勾勒出来的矩形的最大面积. 以上是柱状图的示例,其中每个柱子的宽度 ...

随机推荐

  1. C# 应用 - 多线程 3) Task.Factory

    1. 与 Task.Run() 的区别: 先看一下源码: public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable { pu ...

  2. 翻译:《实用的Python编程》06_01_Iteration_protocol

    目录 | 上一节 (5.2 封装) | 下一节 (6.2 自定义迭代) 6.1 迭代协议 本节将探究迭代的底层过程. 迭代无处不在 许多对象都支持迭代: a = 'hello' for c in a: ...

  3. python程序控制结构

    一:顺序结构 顺序结构的程序是指程序中的所有语句都是按照书写顺序逐一执行的,但是顺序结构的程序功能有限. 二:选择结构 选择结构也称为分支结构,用于处理在程序中出现两条或更多执行路径可供选择的情况.选 ...

  4. OpenGL光照计算中法线矩阵原理及推到过程

    问题起源 在计算漫反射关照时,需要用到法线,通过法线和光线的点乘值,计算漫反射的产生的光线强度,所以需要从顶点着色器中将法线数据传递到片源着色器中,但是片源着色器中的顶点坐标是经过了模型矩阵变化过的世 ...

  5. 每天自学两小时Python,整理了最详细的学习路线和规

    上次这篇文章每天自学两小时Python,三个月学通月入20K主要是给大家整理了学习资料视频和PDF书籍,很多需要的都关注私信领取了. 很多朋友领取之后都问我教程有了那么应该从哪去开始学习呢,私信太多我 ...

  6. 鸿蒙运行报错:Failure[INSTALL_PARSE_FAILED_USESDK_ERROR] Error while Deploying HAP

    问题描述 近期,使用DevEco-Studio新建手机类型的工程,编译成功,发布到模拟器(鸿蒙P40)时出错,如下图: 原因分析 本地DevEco-Studio使用的SDK版本与设备(P40)不匹配导 ...

  7. 加快Python运行速度

    01 使用哈希表的数据结构 如果在程序中遇到大量搜索操作时,并且数据中没有重复项,则可以使用查找而不是循环.举例如下: items = ['a', 'b',..,'100m'] #1000s of i ...

  8. [图论]最优布线问题:kruskal

    最优布线问题 目录 最优布线问题 Description Input Output Sample Input Sample Output Hint 解析 代码 Description 学校有n台计算机 ...

  9. Jmeter(四十二) - 从入门到精通进阶篇 - Jmeter配置文件的刨根问底 -番外篇(详解教程)

    1.简介 为什么宏哥要对Jmeter的配置文件进行一下讲解了,因为有的童鞋或者小伙伴在测试中遇到一些需要修改配置文件的问题不是很清楚也不是很懂,就算修改了也是模模糊糊的.更有甚者觉得那是禁地神圣不可轻 ...

  10. filesort排序原理

    在执行计划中,可能经常看到有Extra列有filesort,这就是使用了文件排序,这当然是不好的,应该优化,但是,了解一下他排序的原理也许很有帮助,下面看一下filesort的过程: 1.根据表的索引 ...