LeetCode Largest Rectangle in Histogram

LeetCode解题之Largest Rectangle in Histogram

原题

给定一个柱状图,求它能包含的最大的矩形的面积。如下图中阴影部分就是要求的矩形。

注意点:

  • 所有的柱的宽度都为1

例子:

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

输出: 10

解题思路

这道题卡了很久,一直没想到好的解决方案。查了一些资料,比较优雅的方法是通过栈来解决。

首先明确最终矩形的高度一定是某一个柱的高度,以上面的例子为例,可能是2,1,5,6,2,3中的一个,如果像这样把每个柱穷举出来,并尝试向两边扩展来得到最大面积,时间复杂度就太大。仔细想一想,为什么要尝试向两边扩展,如例子中的第二个2(以它为高的话最多可以涵盖4个柱),因为它的左右两边相邻的柱都有比它高的,也就是说柱的高度不是有序的,如果我们能得到一个有序递增的排列,那么就只要像右扩展,而不要向左扩展了,因为左边的柱比它自己低。

依次遍历柱状结构,如果是递增的则压栈,如果不是则把比它高的柱依次弹出(只弹出比当前柱高的可以保证把当前柱压栈后,栈中的柱依旧是依次递增的),并计算以该柱为高的矩形的面积。计算面积时,宽度应该是栈顶元素到遍历到元素之间的宽,如当弹出第二个2(2后面没有比它小的元素,为了使该元素能顺利弹出,在原柱状图末尾加一个0)时,栈顶元素是1,这样就能方便计算出宽度为4。还有一个问题是弹出1时栈中没有元素,无法计算宽度,所以在初始化时要在栈底加一个-1来应对所有元素都出栈的情况。

AC源码

class Solution(object):
    def largestRectangleArea(self, heights):
        """ :type heights: List[int] :rtype: int """
        heights.append(0)
        stack = [-1]
        result = 0
        for i in range(len(heights)):
            while heights[i] < heights[stack[-1]]:
                h = heights[stack.pop()]
                w = i - stack[-1] - 1
                result = max(result, h * w)
            stack.append(i)
        heights.pop()
        return result


if __name__ == "__main__":
    assert Solution().largestRectangleArea([2, 1, 5, 6, 2, 3]) == 10

欢迎查看我的Github (https://github.com/gavinfish/LeetCode-Python) 来获得相关源码。

你可能感兴趣的:(LeetCode,算法,python,栈,柱状图)