84. 柱状图中最大的矩形
题目
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-rectangle-in-histogram
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解思路
1>源代码
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
n = len(heights)
left, right = [0] * n, [0] * n
mono_stack = list()
for i in range(n):
while mono_stack and heights[mono_stack[-1]] >= heights[i]:
mono_stack.pop()
left[i] = mono_stack[-1] if mono_stack else -1
mono_stack.append(i)
mono_stack = list()
for i in range(n - 1, -1, -1):
while mono_stack and heights[mono_stack[-1]] >= heights[i]:
mono_stack.pop()
right[i] = mono_stack[-1] if mono_stack else n
mono_stack.append(i)
if n>0:
ans = max((right[i] - left[i] - 1) * heights[i] for i in range(n))
return ans
else:
return 0
2>算法介绍
本题我在面试中遇到过,当时面试官出题之后我就直接想到了暴力方法,我直接算出所有矩形的面积取最大。当然这个方法本身没有任何问题,实现起来也很容易,但当面试官要求我进行优化我就傻眼了。于是我在面试中很诚实的说:暂时我只能想到这种方法。
我们归纳一下枚举「高」的方法:
首先我们枚举某一根柱子 i 作为高 h = heights[i];
随后我们需要进行向左右两边扩展,使得扩展到的柱子的高度均不小于 h。换句话说,我们需要找到左右两侧最近的高度小于 h 的柱子,这样这两根柱子之间(不包括其本身)的所有柱子高度均不小于 h,并且就是 i 能够扩展到的最远范围。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/zhu-zhuang-tu-zhong-zui-da-de-ju-xing-by-leetcode-/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
以上是LeetCode本题题解中提供给我们的优化思路,想明白了这一点之后,我们则可以进行算法优化。由于本题我们是要求出 左右两侧最近的高度小于 h 的柱子 ,于是我们想到单调栈。单调栈的具体思想在这里就不细谈,这个算法能以O(n)的时间复杂度求出小于当前值且最接近当前值的元素。