leetcode -- Largest Rectangle in Histogram -- 重点,多看几遍

https://leetcode.com/problems/largest-rectangle-in-histogram/

重点!!用到了递增栈,increasing stack

思路参考http://blog.csdn.net/u013027996/article/details/43198421
http://tech-wonderland.net/blog/leetcode-largest-rectangle-in-histogram.html

有O(n)算法

code参考http://www.cnblogs.com/zuoyuan/p/3783993.html

这里保持一个height的递增栈,直到current bar小于stack 的top bar,这个时候,我们就以current bar为rectangle right bound,不包括这个current bar. 然后从stack中的top bar开始逐个向左找left bound, 一直找到一个bar小于current bar. 这个过程中,

第一个rectangle 是, stack的top bar 作为left bound, current bar 作为right bound,即矩形面积就是这个stack top bar的面积,

第二个rectangle就是在第一个stack top bar被pop之后,现在的top bar(利用其left side作为左边界)与current bar (利用其left side作为右边界)围城的矩形面积。
……

最后要注意可能给定的height array本身就是递增的,所以要在最后,再以height 数组右边界为矩形的右边界逐个pop stack直到stack.empty()

这里height[i] == stackHeight[len(stackHeight)-1]这种情况是不进stack,也不处理的,所以这里要引入stackIndex。自己可以举例[2,2,2], 这里还是会用stackIndex来准确计算出水平方向的边长

注意!!1
这里需要特别注意的一点就是,注意都没有等号,并且pop完了之后,stackindex.append(lastIndex)而不是stackindex.append(i).入下图所示,当stackindex = [0,1,2]的时候,会pop成只有0,然后这个时候不应该append(3)这个index,而是要append(1),即最后一个被pop的index。这个可以理解为对于3这个矩形条来说,他的矩形最左边的index是1,因为while会使得3这个矩形条大于stackheight的top。入下图所示

leetcode -- Largest Rectangle in Histogram -- 重点,多看几遍_第1张图片

class Solution:
    # @param height, a list of integer
    # @return an integer
    # @good solution!
    def largestRectangleArea(self, height):
        maxArea = 0
        stackHeight = []
        stackIndex = []
        for i in range(len(height)):
            if stackHeight == [] or height[i] > stackHeight[len(stackHeight)-1]:#注意这里没有等号
                stackHeight.append(height[i]); stackIndex.append(i)
            elif height[i] < stackHeight[len(stackHeight)-1]:#注意这里也没有等号
                lastIndex = 0
                while stackHeight and height[i] < stackHeight[len(stackHeight)-1]:#这里也没有等于
                    lastIndex = stackIndex.pop()
                    tempArea = stackHeight.pop() * (i-lastIndex)
                    if maxArea < tempArea: maxArea = tempArea
                stackHeight.append(height[i]); stackIndex.append(lastIndex)#这里要注意是append lastIndex而不是i
        while stackHeight:
            tempArea = stackHeight.pop() * (len(height) - stackIndex.pop())
            if tempArea > maxArea:
                maxArea = tempArea
        return maxArea

自己重写了一遍这个code,供自己复习

class Solution(object):
    def largestRectangleArea(self, height):
        """ :type height: List[int] :rtype: int """
        stackheight, stackindex = [], []
        maxArea = 0
        for i in range(len(height)):
            if stackheight == [] or height[i] > stackheight[-1]:
                stackheight.append(height[i])
                stackindex.append(i)
            elif height[i] < stackheight[-1]:
                lastIndex = 0
                while stackheight and height[i] < stackheight[-1]:
                    h, lastIndex = stackheight.pop(), stackindex.pop()
                    area = h * (i - lastIndex)
                    maxArea = max(area, maxArea)
                stackheight.append(height[i])
                stackindex.append(lastIndex)#特别要注意这里是append lastIndex 而不是i
        length = len(height)
        while stackheight:
            h, lastIndex = stackheight.pop(), stackindex.pop()
            area = h * (length - lastIndex)
            maxArea = max(area, maxArea)
        return maxArea

自己重写

有bug的code如下,要注意不要用while,用 for.

class Solution(object):
    def largestRectangleArea(self, height):
        """ :type height: List[int] :rtype: int """
        if len(height) == 0: return 0
        i = 0
        stackheight = []
        stackindex = []
        maxArea = 0
        while i < len(height):

            while i < len(height) and (stackheight == [] or height[i] > stackheight[-1]):
                stackheight.append(height[i])
                stackindex.append(i)
                i += 1

            last = stackindex[-1]
            while i < len(height) and stackheight and height[i] < stackheight[-1]:
                last = stackindex.pop()
                maxArea = max(maxArea, stackheight.pop()*(i - last))
            stackheight.append(height[i])
            stackindex.append(last)
            i += 1
        while stackheight:
            maxArea = max(maxArea, stackheight.pop() * (len(height) - stackindex.pop()))

        return maxArea

正确的可以AC的code

class Solution(object):
    def largestRectangleArea(self, height):
        """ :type height: List[int] :rtype: int """
        if len(height) == 0: return 0
        i = 0
        stackheight = []
        stackindex = []
        maxArea = 0
        for i in xrange(len(height)):#这里注意要用for

            if stackheight == [] or height[i] > stackheight[-1]:#这里注意加上如果stack为空,并且没有等号
                stackheight.append(height[i])
                stackindex.append(i)
            elif height[i] < stackheight[-1]:#这里是没有等号
                lastindex = 0#也可以是stackheight[-1]。
                #这里的意思就是说对于height[i]来说,比height[i]高的边长最长的矩形的index是多少。

                while stackheight != [] and stackheight[-1] > height[i]:
                    lastindex = stackindex.pop()
                    maxArea = max(maxArea, (i - lastindex) * stackheight.pop())
                stackheight.append(height[i])
                stackindex.append(lastindex)#这里是要append lastindex
        length = len(height)
        while stackheight:
            maxArea = max(maxArea, (length - stackindex.pop()) * stackheight.pop())
        return maxArea

你可能感兴趣的:(leetcode -- Largest Rectangle in Histogram -- 重点,多看几遍)