2022-11-16 每日打卡:单调栈解决最大矩形问题(一维直方图,二维最大红矩形)

news2025/1/15 23:43:37

每日打卡:单调栈解决最大矩形问题(一维直方图,二维最大红矩形)

柱状图中最大的矩形

在这里插入图片描述

思路

这个题最明显的思路就是:矩形面积=底×高。

  • 版本1:底的长度可以通过二重循环来完成,高通过循环来寻找最小值。
  • 版本2:底的长度可以通过二重循环来完成,高通过线性比较当前遍历到的高度和之前记录的max(minh, h)

可以发现,通过遍历底×高的方法来做,优化的上限就到此为止。那么我们想一想,能否通过遍历高×底的思想呢?

如果能通过遍历每个高,这只需要O(n)的时间复杂度,同时找到以这个高度为高的最大矩形的底有多长就好了!

考虑对某一个高而言,它的底究竟是什么?如下图(参考链接)所示:
在这里插入图片描述

也就是我们如果能在遍历到下标为2的柱子的时候,得到这两个信息就好了:

  • 左侧比他矮的最近的柱子的下标,也就是1
  • 右侧比他矮的最近的柱子的下标,也就是4

我们想到一种结构:单调栈可以存储单调递增/递减的柱子下标。这样上面提到的第一个信息,也就是遍历时左侧比他矮的最近的柱子下标就知道了。

那么右边的呢?

右边的相当于现在的高度而言其实是“未来”的,也就是还没遍历到的。那我们考虑在“未来”的遍历过程中,无非是出现“比现在这个高度高” 和 “比现在这个高度低” 两种情况,边界的等于我们稍后再讨论。

当遇到比现在高度高时,就需要添加到栈中。因为栈必须维护 “前一个存储的下标是后一个存储下标的左边界”

当遇到比现在高度低的时候,其实就是上面提到的第二个需要知道的信息,右侧比他矮的第一个柱子的下标!

下面我们来整理一下思路:

  • 遍历每个高度,记作height
  • 单调栈维护左侧比height矮的最近的柱子的下标。称为lo。
  • 当右侧出现第一个比height矮的柱子时,计算height×底,此时底的长度是(hi-lo-1)。

而在代码实现的过程中,因为栈具有记录功能,所以上面我们所说的遍历每个高度,计算面积的过程其实不是在当前高度被遍历到的时候计算的,因为此时hi的值不知道。

我们使用栈记录了额外的信息,也就是待计算的高度height。把真正计算面积,更新最大面积的过程延迟到了hi出现的时候!我认为这才是栈作为数据结构之所以有用的原因。

而单调栈则相比栈记录了更多的信息,也就是比height矮的最近的柱子的下标lo就是height的前一个位置。

代码实现

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        ans, stack = 0, []

        # 添加哨兵
        heights = [0]+heights
        heights.append(0)

        # 左侧限位lo, 右侧限位hi
        lo, hi = 0, 0
        for hi, tmp in enumerate(heights):
        	# 注意边界条件,栈为空时直接入栈
            while (stack and tmp<heights[stack[-1]]):
                height = heights[stack.pop()]
                lo = stack[-1]
                ans = max(ans, height*(hi-lo-1))
            stack.append(hi)
        return(ans)

复杂度分析

时间复杂度

在遍历数组时,直方图的每根柱子都入栈,出栈一次,并且在每个柱子的下标出栈时计算以它为顶的最大矩形面积,这些操作对每根柱子而言复杂度都是O(1),故总的时间复杂度为O(n)

空间复杂度

需要一个辅助栈,栈中可能有O(n)根柱子在数组中的下标,故空间复杂度为O(n)

矩阵中最大的矩形

有了上面的铺垫,将一维的情况扩展至二维即可。如题:
在这里插入图片描述

如果把每一行/每一列看作一个heights数组,那么问题就可解了。

考虑每一行/每一列的heights应该是多少?

这里以行为例,对于第一行而言,heights应该是【10100】,第二行,则是【20211】,我们可以通过动态规划的方法更新该数组,规律为:

  • 如果位置为1,则height+1
  • 否则height变成0

为什么是正确的?因为最大的矩阵的高度永远被限制在最小的height中,所以即使我们看似加入了y轴以下的部分(有的height出现的位置早,有的出现的位置晚),也会被最小的height限制住。

代码非常简单,只是在每次调用计算柱状图中最大的矩形的外面,加了新的循环,用于更新heights数组。

class Solution:
    def maximalRectangle(self, matrix: List[str]) -> int:
        if not matrix:
            return 0
        col_len = len(matrix[0])
        
        # 记录当前行每一个“柱子”的高度,0和最后一位是哨兵
        heights = [0 for i in range(col_len+2)]
        ans, stack = 0, []
        for line in matrix:
            for i in range(col_len):
                # 如果是1,则长度为上一行长度+1,否则为0
                heights[i+1] = heights[i+1]+1 if line[i]!='0' else 0

            # 栈清空
            stack.clear()
            # 左侧限位lo, 右侧限位hi
            lo, hi = 0, 0
            for hi, tmp in enumerate(heights):
                # 注意边界条件,栈为空时直接入栈
                while (stack and tmp<heights[stack[-1]]):
                    height = heights[stack.pop()]
                    lo = stack[-1]
                    ans = max(ans, height*(hi-lo-1))
                stack.append(hi)
        return(ans)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/10450.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

44、Spring AMQP 数据转换器

1、操作案例 2、发送一个对象到队列中 3、控制台查看 4、使用消息转换器 5、消费者接收消息&#xff0c; 传递什么类型&#xff0c;就接受什么类型&#xff0c;发送方与接收方所使用的消息转换器必须对应 6、总结分析 默认的消息推送是通过JDK序列化的方式进行的&#xff0c;…

【STM32+cubemx】0029 HAL库开发:HMC5883L磁力计的应用(电子指南针)

今天我们来学习电子磁力计HMC5883L的使用。先介绍磁力计的基础知识&#xff0c;再给一个获取磁力计数据的例子&#xff0c;最后讲解HMC5883L磁力计的校准&#xff0c;以及一些使用中的经验。 1&#xff09;HMC5883L磁力计的基础知识 磁力计是用来测量磁场强弱&#xff08;也就…

Android 录音没有声音,设置AudioSource.VOICE_CALL直接MediaRecorder.start异常等系列问题

一、我的需求&#xff1a;来电后&#xff0c;我的三方应用主动开启录音&#xff0c;挂断后结束录音&#xff0c;查验音频 我遇到的问题&#xff1a;录制的音频没有声音。 通过各种尝试&#xff0c;结果如下 &#xff1a;设置不同的录音来源的效果 MediaRecorder API\创建MediaR…

Springboot 结合 MQTT、Redis ,对接硬件以及做消息分发,最佳实践

Springboot 结合 mqtt、redis对接硬件以及做消息分发&#xff0c;最佳实践 一&#xff0c;认识 需要了解EMQX 基本知识原理&#xff0c;不了解的可以查看我之间的博客&#xff0c;以及网上的资料&#xff0c;这里不在过多撰述。 二&#xff0c;开发思路 这里以对接雷达水位计…

【最优化理论】03-无约束优化

无约束优化无约束优化问题无约束优化问题的应用无约束优化问题的最优性条件无约束-凸函数-最优性条件&#xff08;充要&#xff09;无约束-一般函数-最优性条件必要条件一阶必要条件&#xff1a;梯度为0二阶必要条件&#xff1a;hessian矩阵半正定充分条件二阶充分条件&#xf…

元宇宙-漫游世界后与Cocos一起看湖南卫视直播

使用参考资源 CocosCreator v3.6.2 cocomat 腾讯开源公共组件框架 Cocos Creator 3D特制 Video MeshRender 播放器&#xff08;Cocos商店购买&#xff09; TcPlayer 腾讯开源 Web 播放器 视频流 hls 库 正文 场景漫游引发的思考 元宇宙&#xff0c;虚拟世界。OK&#xff0c;…

【UI编程】将Java awt/swing应用移植到JavaFX纪实

1. 背景 最近想做一个实用的小工具&#xff0c;能屏幕截图&#xff0c;录屏和录制课件&#xff0c;简单的图像处理&#xff0c;和制作gif表情包。翻出了很久以前用Java awt/swing写的一个屏幕截图小程序&#xff0c;能运行&#xff0c;但是屏幕截图到剪贴板后&#xff0c;发现…

深入理解JavaScript-this关键字

先说结论&#xff1a;谁调用它&#xff0c;this 就指向谁 前言 在讲 Function、作用域 时&#xff0c;我们都讲到了 this&#xff0c;因为 JavaScript 中的作用域是词法作用域&#xff0c;在哪里定义&#xff0c;就在哪里形成作用域。而与词法作用域相对应的还有一个作用域叫…

MP157-0-遇见的问题及解决办法

MP157-0-遇见的问题及解决办法1.Win11运行VMware15虚拟机崩溃死机&#xff0c;蓝屏。1.Win11运行VMware15虚拟机崩溃死机&#xff0c;蓝屏。 时间&#xff1a;2022.11.15 解决办法&#xff1a; Hyper-V方案。 打开控制面板-程序-启用或关闭Windows功能&#xff0c;可能你的电…

【JavaScript高级】03-JavaScript内存管理和闭包

JavaScript内存管理和闭包JavaScript内存管理垃圾回收机制算法常见的GC算法-标记清除闭包闭包的概念理解闭包的形成过程闭包的内存泄露JavaScript内存管理 JavaScript会在定义数据时为我们分配内存&#xff1a; JS对于原始数据类型内存的分配会在执行时&#xff0c;直接在栈空…

Sentinel使用教程

文章目录一、Sentinel简介1.sentinel介绍2.sentinel应用场景3.sentinel与hystrix4.sentinel组件介绍二、Sentinel使用说明1.控制台Dashboard2.Sentinel 流量控制和熔断降级3.常见报错解决一、Sentinel简介 1.sentinel介绍 Sentinel 是由阿里巴巴中间件团队开发的开源项目&…

Java三大特性篇之——继承篇(超详解的好吧!)

&#x1f60d;&#x1f60d;&#x1f60d;欢迎欢迎欢迎欢迎&#xff0c;我的朋友&#xff0c;答应我&#xff0c;看完好吗&#xff1f;&#x1f974; 文章目录前言&#xff1a;何为继承&#xff1f;不谈钱的继承实现&#xff01;嘘&#xff1a;偷偷访问父类的私密成员&#xff…

OkHttp相关知识(二)

okhttp中一次网络请求的大致过程&#xff1a; Call对象对请求的封装 dispatcher对请求的分发 getResponseWithInterceptors()方法 一、OkHttp同步方法总结&#xff1a; 创建OkHttpClient和构建了携带请求信息的Request对象将Request封装成Call对象调用Call的execute()发送…

【11.16】Codeforces 刷题

DP\text{DP}DP &#xff1a;&#xff08;今天做的这两道都没啥 DP 相关来着 D. Match & Catch 题意&#xff1a; 给定两个字符串 1≤∣s1∣,∣s2∣≤50001\leq |s_1|,|s_2|\leq 50001≤∣s1​∣,∣s2​∣≤5000 &#xff0c;求最短的满足各只出现一次的连续公共字串。 思…

实验27:红外遥控三级控速风扇实验

今天介绍一个稍微复杂点的实验,复杂在设计和代码 ——OK,受了抖音西湖大学教授刺激,任何人都可以做研究 ——实验:红外遥控三级风速小电扇 ——每按一下CH-,风速从1-2-3-1-2-3-1循环 ——按下CH+,风扇停止 ——没有背景音乐目的是听风扇声音大小判断风速 OK实验介绍完了…

五个可以永远相信的神仙网站推荐

早八的我们是不是偶尔会处在焦虑中呢&#xff1f;一方面年轻人工作压力大&#xff0c;另一方面我们偶尔会感慨我们的碌碌无为&#xff0c;不知道怎样提升自己。今天为大家推荐五个焦虑时可以随手打开看&#xff0c;不知不觉悄悄提升自己的软件。 1.全历史 全历史是一个把历史以…

《元宇宙2086》亮相金鸡奖中国首部元宇宙概念院线电影启动

2022年中国金鸡百花电影节暨第35届中国电影金鸡奖于11月10日至12日在福建厦门举办&#xff0c;中国动漫集团控股子公司北京中文发文化发展有限公司与《元宇宙2086》作者高泽龙在金鸡奖创投论坛正式签约&#xff0c;宣布将共同启动筹拍中国首部元宇宙概念的院线电影。 当日下午&…

如何在Docker中安装MySQL数据库

1、Docker环境 视频教程&#xff1a;https://www.bilibili.com/video/BV1xv4y1S7kA 2、搜索镜像 https://hub.docker.com/网站搜索MySQL&#xff0c;确定其安装版本&#xff0c;这里安装8.0.31版&#xff1b; 3、拉取镜像 [rootlocalhost ~]# docker pull mysql:8.0.31 8.…

市级专精特新的申报条件

一、基本条件&#xff1a;&#xff08;各市政策不同具体情况也不同&#xff0c;下面为济南市企业的申报条件&#xff09; 1、连续经营3年以上&#xff0c;上年度企业营业收入在800万元以上&#xff1b; 2、近两年营业收入复合增长率不低于8%&#xff08;2021年参照国 家级调…

Nginx 反向代理

title: Nginx 反向代理 date: 2022-11-16 10:24 tags: [Nginx,反向代理,正向代理,代理] 文章目录〇、问题一、前言二、正向代理&反向代理2.1 正向代理2.2 反向代理三、Nginx配置反向代理参考更新〇、问题 什么是正向代理&#xff1f;什么是反向代理&#xff1f;Nginx如何配…