代码随想录27期|Python|Day54|​单调栈|​42. 接雨水|84. 柱状图中最大的矩形

42. 接雨水

根据常识可以归纳出,对于每一列所能够存住的水的高度

Height = min(LeftMax, RightMax) - height

也就是,当前列的存水高度 = 左侧和右侧柱子的最大高度的较小值,减去当前列的柱子高度,所得到的差值。

可以验证第4列:Height = min(2, 3) - 1 = 1,其中2是最左边的最高的柱子(3列)高度,3是右边最高的柱子的高度(7列),1是当前4列的柱子的高度。

解法一:双指针

双指针解法主要的思想是牺牲空间换时间,也就是在最后遍历全部的柱子高度求解雨水高度之前,先把每一列所对应的最左边和最右边的最高的柱子算出来。因此需要两个for循环,循环前都需要进行初始化。

        leftmax[0] = height[0]
        for i in range(1, len(height)):
            leftmax[i] = max(height[i], leftmax[i-1])

        rightmax[len(height) - 1] = height[len(height) - 1]
        for i in range(len(height) - 2, -1, -1):
            rightmax[i] = max(height[i], rightmax[i+1])

至此,已经得到了每一列的左右最高的柱子,下面只需要遍历最后一次柱子,按照公式进行求解就可以了。 

class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """

        # 双指针解法
        res  = 0
        leftmax = [0] * len(height)
        rightmax = [0] * len(height)

        leftmax[0] = height[0]
        for i in range(1, len(height)):
            leftmax[i] = max(height[i], leftmax[i-1])

        rightmax[len(height) - 1] = height[len(height) - 1]
        for i in range(len(height) - 2, -1, -1):
            rightmax[i] = max(height[i], rightmax[i+1])

        for i in range(len(height)):
            Height = min(leftmax[i], rightmax[i]) - height[i]
            if Height > 0:
                res += Height
        return res

解法二:单调栈

单调栈的性质是能够维护一个有顺序的高度索引的序列。

为什么是按照行来计算呢?

因为我们在一次操作中只能得到当前列(中间列)和左右两边列的高度,而不能得到左边最高值和右边最高值。

举个例子,对于列5(高度0),我们一次只能获取到列4(高度1)和列6(高度1),根据计算智能得到水位高度为1,但是因为看不到左右最高值,所以列5的上方是否还有水(列5的实际水位高度是2)就没有方法获取到。

单调栈解法的原理

维护一个从栈底部到顶部为单调减高度的索引栈(栈的开口向右,可以想象成一个向右下的斜坡),那么在遍历到一个比栈顶元素大的元素的时候,恰好组成了一个V字,也就是中间低,两边高。这三个数字(栈顶、栈顶-1(左边的高度索引),遍历到的height(右边高度索引))就组成了一个储水的结构。

此时,只需要计算出左右索引之间的距离,在计算出左右索引对应的高度的最小值,即可得到储水的体积。

然后,栈顶的元素相当于被使用了,所以需要弹出,再判断当前遍历到的高度和新的栈顶元素的高度的大小(也就是之前的左侧的索引),最后,直到遍历到的元素比栈顶元素小(或者相等),再加入到栈中,组成一个递减的序列。

class Solution(object):
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        # 单调栈解法
        res = 0
        stack = []
        for i in range(len(height)):
            while stack and height[i] > height[stack[-1]]:
                mid_height = stack.pop()  # 弹出来的是中间柱子的高度索引(作为最低的底部的高度)
                if stack:  # 确保当前的stack还有值,也就是左边界存在
                    h = min(height[stack[-1]], height[i]) - height[mid_height]
                    w = i - stack[-1] - 1
                    res += h * w
            stack.append(i)
        return res

84. 柱状图中最大的矩形

什么时候能够取到最大的矩形面积?

以一个柱子作为矩形高度的基准,向左向右遍历到的第一个比他小的柱子,作为矩形的左右边界,此时计算出的矩形面积是该柱子为最大高度基准时最大的。

2,2,34,5,4,33

蓝色边界的面积:3 * 5 = 15;

红色边界的面积:7 * 2 = 14;

所以可以确定,对于局部值而言,最大的面积在两侧第一个小于中心高度的区间之间。

解法一:双指针

对于本题,因为需要宽度,所以需要在双指针遍历的时候储存左右第一个小于当前高度值的索引。

        leftminidx[0] = -1
        for i in range(1, len(heights)):
            t = i - 1  # i左边的索引
            while t >= 0 and heights[i] <= heights[t]:
                t = leftminidx[t]
            leftminidx[i] = t

以左侧为例,因为需要向左侧拓展,如果一直比当前的柱子高度高,那么就将其索引值设置为自身,直到循环打破,储存第一个小于当前高度的索引。

这样做的好处是,在最后一次求解面积的遍历时,只需要进行面积的计算和结果的更新即可。

class Solution(object):
    def largestRectangleArea(self, heights):
        """
        :type heights: List[int]
        :rtype: int
        """

        # 双指针解法
        res = 0

        leftminidx = [0] * len(heights)
        rightminidx = [0] * len(heights)

        leftminidx[0] = -1
        for i in range(1, len(heights)):
            t = i - 1  # i左边的索引
            while t >= 0 and heights[i] <= heights[t]:
                t = leftminidx[t]
            leftminidx[i] = t
        
        rightminidx[len(heights)-1] = len(heights)
        for i in range(len(heights)-2, -1, -1):
            t = i + 1
            while t <= len(heights) - 1 and heights[i] <= heights[t]:
                t = rightminidx[t]
            rightminidx[i] = t 

        for i in range(len(heights)):
            area = heights[i] * (rightminidx[i] - leftminidx[i] - 1)
            res = max(res, area)
        return res

解法二:单调栈

本题的分析上和接雨水相反,因为接雨水的栈结构实际上是构成了一个谷形来接住雨水,所以找的是第一个大于当前元素的值。但是本题实际上是构成一个山峰,所以需要找到的是第一个小于当前值的索引。

因此,单调栈的顺序是从栈底到栈顶递增。

每次遍历到的值(右边界)、栈顶元素(中间值)、栈顶元素的后一个值(左边界索引)构成了局部最大矩形。

class Solution(object):
    def largestRectangleArea(self, heights):
        """
        :type heights: List[int]
        :rtype: int
        """
        # 单调栈解法
        res = 0
        stack = []
        heights.insert(0,0)  # 加上0防止溢出
        heights.append(0)  # 加上0防止溢出
        
        for i in range(len(heights)):
            while stack and heights[i] < heights[stack[-1]]:
                mid_height = stack.pop()
                if stack:
                    Height = heights[mid_height]  # 中心值作为高度
                    Width = i - stack[-1] - 1  # 不算上两个边界索引
                    # print(stack)
                    res = max(res, Height * Width)
            stack.append(i)

        return res

Day54完结!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何通过OceanBase的多级弹性扩缩容能力应对业务洪峰

每周四晚上的10点&#xff0c;都有近百万的年轻用户进入泡泡玛特的抽盒机小程序&#xff0c;共同参与到抢抽盲盒新品的活动中。瞬间的并发流量激增对抽盒机小程序的系统构成了巨大的挑战&#xff0c;同时也对其数据库的扩容能力也提出了更高的要求。 但泡泡玛特的工程师们一点…

【系统架构师】-论文-2024-2009年系统架构师历年论文题目

2024年5月 大数据Lambda架构的应用与分析 云原生云上DevOps运维应用与分析 模型驱动软件开发方法与应用 论单元测试在软件回归测试中的应用和分析 2023年 论面向对象设计的应用与实现 论多数据源集成的应用与实现 论软件可靠性模型的设计与实现 论边缘计算技术的设计与实现 …

【Linux】3.切换操作系统

文章目录 1. 为什么要切换操作系统2. 如何备份操作系统文件3.如何切换操作系统4. 在Ubuntu操作系统中恢复文件 1. 为什么要切换操作系统 由于CentoS官方宣布不再维护了&#xff0c;为了避免服务器安全和各类环境问题&#xff0c;我将云服务器改为Ubuntu操作系统。 Ubuntu 不仅…

HarmonyOS开发实战( Beta5.0)自动生成动态路由实践

鸿蒙HarmonyOS开发往期必看&#xff1a; HarmonyOS NEXT应用开发性能实践总结 最新版&#xff01;“非常详细的” 鸿蒙HarmonyOS Next应用开发学习路线&#xff01;&#xff08;从零基础入门到精通&#xff09; 介绍 本示例将介绍如何使用装饰器和插件&#xff0c;自动生成动…

使用Azure Devops Pipeline将Docker应用部署到你的Raspberry Pi上

文章目录 1. 添加树莓派到 Agent Pool1.1 添加pool1.2 添加agent 2. 将树莓派添加到 Deployment Pool2.1 添加pool2.2 添加target 3. 添加编译流水线3.1 添加编译命令3.2 配置触发器 4. 添加发布流水线4.1 添加命令行4.2 配置artifact和触发器 5. 完成 1. 添加树莓派到 Agent P…

三菱FX5U CPU 内置以太网功能

什么是内置以太网功能FX5CPU模块内置以太网通信端口&#xff0c;可以利用TCP/IPUDP/IP通信协议&#xff0c;经过以太网(100BASE-TX、10BASET)与计算机或其他以太网设备进行通信。 MELSOFT连接 与MELSOFT产品连接的功能&#xff0c;MELSOFT产品主要指三菱的软件及GOT。 SLMP通信…

Kafka原理剖析之「Topic创建」

一、前言 Kafka提供了高性能的读写&#xff0c;而这些读写操作均是操作在Topic上的&#xff0c;Topic的创建就尤为关键&#xff0c;其中涉及分区分配策略、状态流转等&#xff0c;而Topic的新建语句非常简单 bash kafka-topics.sh \ --bootstrap-server localhost:9092 \ // …

【GBase 8c V5_3.0.0 分布式数据库常用维护命令】

一、查看数据库状态/检查&#xff08;gbase用户&#xff09; 1.gha_ctl monitor 使用gha_ctl monitor查看节点运行情况(跟dcs的地址和端口) gha_ctl monitor -c gbase -l http://172.20.10.8:2379 -Hall |coordinator | datanode | gtm | server|dcs:必选字段。指定查看哪类集…

Oracle EBS AP预付款行分配行剩余预付金额数据修复

系统环境 RDBMS : 12.1.0.2.0 Oracle Applications : 12.2.6 问题情况 AP预付款已验证和自动审批但是未过账已经AP付款但是又撤消付款并且未过账问题症状 AP预付款暂挂: AP预付款行金额(等于发票金额)与分配行金额不相等: 取消AP预付款提示如下:

基于Python的B站热门视频可视化分析与挖掘系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 随着互联网视频平台的迅猛发展&#xff0c;如何从海量的数据中提炼出有价值的信息成为了内容创作者们关注的重点之一。B站&#xff08;哔哩哔哩&#xff09;作为国内领先的年轻人文化社区&#xf…

08 vue3之认识bem架构及less sass 和scoped

bem架构 他是一种css架构 oocss 实现的一种 &#xff08;面向对象css&#xff09; &#xff0c;BEM实际上是block、element、modifier的缩写&#xff0c;分别为块层、元素层、修饰符层&#xff0c;element UI 也使用的是这种架构 1. BEM架构 1. 介绍 1. BEM是Block Element M…

美联社发稿推广中必备的6个社交媒体平台

社交媒体是现代社会中不可或缺的一部分&#xff0c;它已经成为了信息传播、群体交流和网络推广的重要工具。对于彭博社这样的专业媒体来说&#xff0c;充分利用社交媒体平台可以更好地推广自己的新闻报道和文章。 在这篇文章中&#xff0c;我们将介绍彭博社发稿推广中必备的六…

SpringBoot实现房产销售系统全解析

第二章关键技术的研究 2.1相关技术 房产销售系统是在Java MySQL开发环境的基础上开发的。Java是一种服务器端脚本语言&#xff0c;易于学习&#xff0c;实用且面向用户。全球超过35&#xff05;的Java驱动的互联网站点使用Java。MySQL是一个数据库管理系统&#xff0c;因为它的…

2024/9/9 408“回头看”:b树

B树是什么&#xff1f;有什么作用&#xff1f;B树的插入和删除具体细节是什么&#xff1f;除了B树还有一个是B&#xff0b;树、还是B-树&#xff0c;他们有什么区别&#xff0c;又有什么相同点&#xff1f; b树在王道考研查找这一章&#xff0c;所以他的主要作用就是查找。 在…

spring常用注解(10)@Order

一、 1、作用 加Order()注解&#xff0c;在注解中加入数字&#xff0c;数字越小&#xff0c;优先级越高&#xff0c;最先执行。 2、使用方法 &#xff08;1&#xff09;自定义顺序 Component Order(1) public class XxxFilter extends OncePerRequestFilter{}Component Or…

Python编码系列—Python工厂方法模式:构建灵活对象的秘诀

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

P3565 [POI2014] HOT-Hotels

~~~~~ P3565 [POI2014] HOT-Hotels ~~~~~ 总题单链接 ~~~~~ 2024.9.10&#xff1a;DP方程有问题&#xff0c;已修改&#xff0c;同时更新了长链剖分优化版本。 思路 ~~~~~ 设 g [ u ] [ i ] g[u][i] g[u][i] 表示在 u u u 的子树内&#xff0c;距离 u u u 为 i i i 的点的…

Android 手机自动化测试工具有哪几种?

一、Android手机自动化测试工具&#xff0c;常用的有这7中&#xff1a; 1、首推Appium&#xff1a; 推荐理由&#xff1a;功能非常强大的移动端自动化测试框架&#xff0c;还免费 下载链接&#xff1a;Appium: Mobile App Automation Made Awesome. Appium是一种被广泛使用的…

SAP自动化-AS02修改资产信息

Python源码 #-Begin-----------------------------------------------------------------#-Includes-------------------------------------------------------------- import sys, win32com.client import os#-Sub Main-----------------------------------------------------…

赵进喜:不透析、不用肾移植,“三维护肾”巧治尿毒症

潜心研究中医药治疗尿毒症等慢性肾脏重症40余年来&#xff0c;北京名老中医&#xff0c;慢性肾病国医大师吕仁和教授医术传承人&#xff0c;全国优秀基层名中医赵进喜总结出弥足珍贵的重症良方&#xff0c;临床应用无数次守护近10万肾病重症患者生命。让仅有22岁的慢性肾衰尿毒…