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

12 篇文章 0 订阅

84. 柱状图中最大的矩形
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。
在这里插入图片描述
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。

在这里插入图片描述

图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
示例:

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


这道和接雨水有点像,但是真的难,开始的时候想到每一个列举单个最大面积,但是会超时。
还是看一下列举面积的情况:

  1. 首先选定一个柱子,左右分别寻找比这个主子高度低的索引坐标,大于等于本柱子高度则跳过。
  2. 找到左右都比其大于等于的最远坐标left, right。使用 right - left +1得到底边的长度,再乘以本柱子的高度,得到单个柱子的最大面积。
    具体的实现代码如下:
from typing import List
class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        size = len(heights)
        res = 0

        for i in range(size):
            left = i
            cur_height = heights[i]#如果左边的高度大于等于本柱子的高度,下标左移
            while left > 0 and heights[left - 1] >= cur_height:
                left -= 1

            right = i#如果右边的高度大于等于本柱子的高度,下标右移
            while right < size - 1 and heights[right + 1] >= cur_height:
                right += 1

            max_width = right - left + 1#计算底面的长度
            res = max(res, max_width * cur_height)#算出本次以本柱子为高度,最大的面积,迭代更新
        return res

作者:liweiwei1419
链接:https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/bao-li-jie-fa-zhan-by-liweiwei1419/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

但是,从上面的例子可以发现,其实只用找一遍就可以,例如 我们可以存储一个递增的高度,如果之后要加进来的高度不是递增的,就表示找到了一个有边界。与此同时,我们由于栈中的高度是递增的,所以栈中的每个高度的左边界就是其左边的值的下标,这么一来,左右边界都确定了,高度也确定,那么就可以计算出每一个的面积,迭代算出最大值。
在这里插入图片描述
例如上图所示:[1, 5, 6]是目前栈中所存储的三个高度,之后的2 < 6,不能假如栈中,这个时候依次弹出栈中的值,比如弹出6,因为栈是一个单向递增栈,所以6的左边界就是5.所以我们可以知道高度位为6 的面积底边就是2下标减去5的下标减一等于1,乘以高度6,得到面积6。

弹出6之后,栈中只有[1, 5],由于待加入的 2 < 5,所以2不能入栈,高度5的面面积待计算,从栈中弹出5,5的左边界为1,右边界还是为不能加入栈的2,因为递增栈,6是大于5的所以右边界还是为2,两个下标之差减一得到底边长度,乘以高度5,得到面积10。

注意
1.弹栈的时候,栈为空;
2.遍历完成以后,栈中还有元素

弹栈的时候,如果栈为空,就没有上一个记录的左边界值,所以在原始列表开头添加一个“哨兵” [0],防止原始列表内的值在栈内全部弹出后,找不到左边界。

加入列表中的值全为递增,那么我们将所有值都入栈后找不到比栈中最上面小的值,于是就出不了栈。所以在原始列表的尾端加上一个“ 哨兵”,此处为[ 0 ]。这样列表内的值都可以出栈了。

from typing import List
class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
      stack = []
      heights = [0] + heights + [0]#建立一个含有哨兵的列表,首尾哨兵,假如是递增的列表数据,也可以弹栈
      res = 0
      for i in range(len(heights)):
      #栈不为空,即有左边界,并且带入栈的高度比栈顶高度小,所以不能入栈,需要出栈计算底边长度和面积
        while stack and heights[stack[-1]] > heights[i]:
          temp = stack.pop()#弹栈,这里面记录的是高度的下标
          #底边长度等于 i(右边界) - stack[-1](左边界) - 1
          res = max(res, (i - stack[-1] -1) * heights[temp])#计算最大面积
        stack.append(i)#如果栈为空则将此下标入栈
      return res

if __name__ == "__main__":
    s = Solution()
    print(s.largestRectangleArea([2,1,5,6,2,3]))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值