题目:
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
示例:
输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10
思路:
方法1,暴力法,会超时的,思路就是遍历整个数组,先固定左端点,然后遍历这个左端点右边的点,包括固定的左端点,找到最小的值,然后计算当前区间长度乘以最小值,就是在这个情况下得到的矩形面积,然后去更新结果得到矩形面积最大值。时间复杂度太高了。
方法2,单调栈,
这里使用单调递增栈,与暴力法不同,换一种思路解决问题,我们遍历数组,对于当前这个值,计算以这个值作为高的矩形面积的值最大可以是多少,那就可以考虑从当前这个位置左右延伸,可以把长度延伸到多少呢,越大越好,那左边或者右边碰见一个比当前位置低的,就不能延伸了,这就是左右边界了,就是左右两边碰见的第一个比当前位置低的。由左右边界决定长度,再乘以高,就是当前位置可构成的最大面积。
在原数组最后加一个哨兵元素,这是为了最后将全部元素都出栈,建立空栈,初始化结果为0,然后开始遍历元素,构建单调递增栈,第一个元素先放进去,然后接着遍历,如果遍历到的元素值大于栈顶元素,就直接将索引放进栈中,说明没有找到右边界,当遍历到的元素值小于栈顶元素,说明找到了右边界,左边界就是栈顶元素的前一个,因为是按递增顺序入栈的,让栈顶元素出栈,得到高的索引,读取高的值,计算矩形面积,更新矩形面积,然后再判断是否满足循环条件,直到跳出循环。
要注意,如果栈本来非空,满足要入栈的元素小于栈顶元素的情况,然后栈顶元素出栈,出栈以后,栈空了,这说明这个元素的前面没有比它小的元素,计算长度的时候是i,就是当前索引,即右侧边界。最后返回面积。
class Solution(object):
def largestRectangleArea(self, heights):
"""
:type heights: List[int]
:rtype: int
"""
heights.append(-1)
stack = []
ans = 0
for i in range(len(heights)):
while stack and heights[i] < heights[stack[-1]]:
h = heights[stack.pop()]# 栈弹出索引,然后读取到值
w = i - stack[-1] - 1 if stack else i
ans = max(ans,h * w)
stack .append(i)
return ans