首页 > 其他分享 >84. 柱状图中最大的矩形

84. 柱状图中最大的矩形

时间:2023-03-20 20:13:48浏览次数:43  
标签:stk cur range heights 索引 柱状图 ans 矩形 84

题目描述

给了一个数组表示柱子的高度,柱子的宽度是1,问能勾勒出的矩形的最大面积?

f1-单调栈

基本分析

  1. 可能的最大矩形面积是咋算的?对某个位置i的高度h[i]来说,最大面积是向左找到最近的比他低的高度l[i], 向右找到最近的比他低的高度r[i], 宽度是r[i] - l[i]- 1
  2. 什么结构可以做到?单调栈能保证在结构中索引递增,且只满足某种单调关系;借助这个关系可以实现找最近的大或者小的需求。
  3. 栈弹出后之前的信息可能就没了,怎么能知道每个位置对应的信息?栈只是个工具,最终的信息另外开数组来存
  4. 三叶的思路是咋样的?(1)定义了l和r数组,l初始化为-1,r初始化为n,表示默认不存在比h[i]值小的数组,这个时候宽度就是n。(2)以维护r数组为例,在枚举h[i]的时候,如果h[stk[-1]] > h[i], 表示在i的左边存在一个值,对这个值来说,i是最近的且小的右端点,r[cur] = i。这么做可以保证i是满足cur 维护左端点类似。(3)这个做法会存在覆盖问题吗?比如对[3, 2, 1, 4]而言,当遍历到索引2(值1)的时候,后栈中弹出1(值是2),r[1]=2; 然后继续弹出3,r[0]=1就错了?需要注意的是,栈中每个元素只会入栈和出栈一次。在枚举索引1的时候,就会stk中就会弹出索引0,r[0]=1; 后面在处理到1的时,栈中只会有[1]这个索引不会覆盖
  5. 官解1的不同?(1)不是对当前i来找之前的cur,表示离cur最近的比h[cur]小的i;而是对当前的i找之前的最近的<h[i]的索引,这个索引。这样做有啥问题?不像i是存在的,这个索引可能不存在,这样就需要有
  6. 官解2怎么做到一次遍历?(1)找左边的套路是一样的,只不过对弹出的cur和三叶的做法类似,前者是>关系,严格对,后者是>=关系,对于类似[1, 2, 2, 1]这种情况,r[1]的值是错误的;(2)但为什么ans不会错?对索引2的未位置来说,答案是对的,最终取最大的时候,保证不会错

单调栈

三叶做法

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        n = len(heights)
        l, r = [-1] * n, [n] *n
        stk = []
        for i in range(n):
            while stk and heights[stk[-1]] > heights[i]:
                # 每次从栈中弹出比h[i]大的索引
                cur = stk.pop()
                # cur位置右边最近的比他h小的索引是i
                r[cur] = i
            stk.append(i)
			
        stk = []
        for i in range(n-1, -1, -1):
            while stk and heights[stk[-1]] > heights[i]:
                cur = stk.pop()
                l[cur] = i
            stk.append(i)

        ans = 0
        for i in range(n):
            area = heights[i] *(r[i] - l[i] - 1)
            ans = max(ans, area)
        return ans

官解1

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        n = len(heights)
        l, r = [-1] * n, [n] * n

        stk = []
        for i in range(n):
            # 都不是i要找的值
            while stk and heights[stk[-1]] >= heights[i]:
                stk.pop()
            if stk:
                l[i] = stk[-1]
            stk.append(i)
        
        stk = []
        for i in range(n-1, -1, -1):
            while stk and heights[stk[-1]] >= heights[i]:
                stk.pop()
            if stk:
                r[i] = stk[-1]
            stk.append(i)
        
        ans = 0
        for i in range(n):
            h = heights[i]
            w = r[i] - l[i] - 1
            ans = max(ans, h * w)
        return ans

官解2 一次遍历

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        n = len(heights)
        l, r = [-1] * n, [n] * n
        stk = []

        for i in range(n):
            while stk and heights[stk[-1]] >= heights[i]:
                cur = stk.pop()
                # 相等的时候,只有最后一个是对的
                r[cur] = i
            if stk:
                l[i] = stk[-1]
            stk.append(i)
        
        ans = 0
        for i in range(n):
            h = heights[i]
            w = r[i] - l[i] - 1
            ans = max(ans, h * w)
        return ans

总结

  1. 不同做法看待问题的角度不一样,可以遍历i的时候把弹出的元素当做索引处理和i的关系;也可以把弹完以后,处理i和stk[-1]的关系;后者更为直接
  2. 正序遍历的时候,索引是递增的。三叶做法是栈顶严格>时候弹,这样i就是cur的一个边界;官解做法是判断栈顶>=的情况弹,最终弹完以后的h[栈顶]会严格<h[i]。前者维护的是一个高度单调上升的栈,允许=;后者是严格单调增,=的情况也会弹出去。

标签:stk,cur,range,heights,索引,柱状图,ans,矩形,84
From: https://www.cnblogs.com/zk-icewall/p/17237541.html

相关文章

  • Qt+OpengGL使用教程(3)绘制矩形
    在Qt+OpengGL使用教程(2)中我们绘制了三角形,接下来我们需要使用qt的API绘制一个矩形,同时参考和对照:LearnOpenGL(3)绘制矩形。一、准备工作元素缓冲对象(EBO) 二、绘制矩......
  • ASEMI代理MMA8451QR1原装NXP车规级MMA8451QR1
    编辑:llASEMI代理MMA8451QR1原装NXP车规级MMA8451QR1型号:MMA8451QR1品牌:NXP/恩智浦封装:QFN-16批号:2023+安装类型:表面贴装型MMA8451QR1汽车芯片MMA8451QR1特征1.95......
  • 384.打乱数组
    打乱数组给你一个整数数组nums,设计算法来打乱一个没有重复元素的数组。打乱后,数组的所有排列应该是 等可能 的。实现Solutionclass:Solution(int[]nums)使用整......
  • RuntimeError: NCCL error in: /pytorch/torch/lib/c10d/ProcessGroupNCCL.cpp:784, u
    ​ 发现报错:RuntimeError:NCCLerrorin:/pytorch/torch/lib/c10d/ProcessGroupNCCL.cpp:784,unhandledsystemerror​编辑想在linux上跑跑mmclassification......
  • 力扣584(MySQL)-寻找用户推荐人(简单)
    题目:给定表 customer ,里面保存了所有客户信息和他们的推荐人。写一个查询语句,返回一个客户列表,列表中客户的推荐人的编号都 不是 2。对于上面的示例数据,结果为: ......
  • TZOJ 5784: 团伙 并查集
    描述 在某城市里住着n个人,任何两个认识的人不是朋友就是敌人,而且满足:1、我朋友的朋友是我的朋友;2、我敌人的敌人是我的朋友;所有是朋友的人组成一个团伙。告诉你关于......
  • 力扣184(MySQL)-部门工资最高的员工(中等)
    题目:表: Employee 表: Department 编写SQL查询以查找每个部门中薪资最高的员工。按 任意顺序 返回结果表。查询结果格式如下例所示。  解题思路:①先将Employ......
  • # yyds干货盘点 # 已知中心点的经纬度和长宽,怎么求矩形左上角和右下角经纬度呀?
    大家好,我是皮皮。一、前言前几天在Python最强王者交流群【缄默】问了一个经纬度处理的问题,这里拿出来给大家分享下。二、实现过程这个问题确实挺难的,像是数学题目,这里【吴超......
  • 工程坐标转换成wgs84坐标系
    工程坐标转换成wgs84坐标系在BIM模型中大多采用工程坐标,但是在前端进行实际位置渲染时,往往出现实际坐标系与工程坐标之间的转换困难问题。基于此,研究了坐标系的转换原理......
  • python opencv绘制矩形框
    绘制矩形框defplot_one_box_PIL4(box,img,fontSize1,color=None,label=None,line_thickness=None):img=Image.fromarray(img)draw=ImageDraw.Draw(img......