代码随想录算法训练营第55天(py)| 单调栈 | 42. 接雨水*、84.柱状图中最大的矩形

news2024/11/18 3:26:23

42. 接雨水*

力扣链接
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
在这里插入图片描述

思路1 暴力

按列来计算。每一列雨水的高度,取决于,该列 左侧最高的柱子和右侧最高的柱子中,较矮的那个柱子的高度。
在这里插入图片描述

h = min(lHeight, rHeight) - height
class Solution:
    def trap(self, height: List[int]) -> int:
        res = 0
        for i in range(len(height)):
            if i == 0 or i == len(height)-1: continue # 如果是两端则不处理
            lHight = height[i-1]
            rHight = height[i+1]
            for j in range(i-1):
                if height[j] > lHight:
                    lHight = height[j] # 找到左侧最高的
            for k in range(i+2,len(height)):
                if height[k] > rHight:
                    rHight = height[k] # 找到右侧最高的
            res1 = min(lHight,rHight) - height[i]
            if res1 > 0:
                res += res1
        return res

但是这样会超时

思路2 双指针优化

把每一个位置的左边最高高度记录在一个数组上(maxLeft),右边最高高度记录在一个数组上(maxRight),这样就避免了重复计算。
对当前水柱i,他左边最高的柱子为maxLeft[i],右边最高的柱子为maxRight[i]

maxLeft[i] = max(height[i], maxLeft[i - 1])
maxRight[i] = max(height[i], maxRight[i + 1]);
class Solution:
    def trap(self, height: List[int]) -> int:
        maxleft = [0] * len(height)
        maxright = [0] * len(height)
        # 记录左侧最大柱子高度
        maxleft[0] = height[0]
        for i in range(len(height)):
            maxleft[i] = max(height[i], maxleft[i-1])
        
        # 记录右侧最大柱子高度
        maxright[-1] = height[-1]
        for i in range(len(height)-2, -1, -1):
            maxright[i] = max(height[i], maxright[i+1])
        
        res = 0
        for i in range(len(height)):
            res1 = min(maxleft[i],maxright[i]) - height[i]
            if res1 > 0:
                res += res1
        return res

思路3 单调栈

在这里插入图片描述
将每条柱子下标依次压栈
一旦发现添加的柱子高度大于栈头元素了,此时就出现凹槽了,栈头元素就是凹槽底部的柱子,栈头第二个元素就是凹槽左边的柱子,而添加的元素就是凹槽右边的柱子。
从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。
求一个元素右边第一个更大元素,单调栈就是递增的;
求一个元素右边第一个更小元素,单调栈就是递减的。

遇到相同的元素,更新栈内下标,就是将栈里元素(旧下标)弹出,将新元素(新下标)加入栈中。要求宽度的时候 如果遇到相同高度的柱子,需要使用最右边的柱子来计算宽度。
在这里插入图片描述
在这里插入图片描述
有三种情况:
情况一:当前遍历的元素(柱子)高度小于栈顶元素的高度 height[i] < height[st.top()]
情况二:当前遍历的元素(柱子)高度等于栈顶元素的高度 height[i] == height[st.top()]
情况三:当前遍历的元素(柱子)高度大于栈顶元素的高度 height[i] > height[st.top()]
先将下标0的柱子压栈,然后遍历height。
如果当前柱子低于栈顶,则入栈(因为要保持栈顶方向的递减)
如果当前柱子等于栈顶,则更新栈顶元素,先出栈再压栈
如果当前柱子高于栈顶,则出栈,记为mid(遇到凹槽了),此时栈顶为凹槽左,当前元素为凹槽右

显而易见,水的高度和宽度为:

h = min(height[st.pop()],height[i])-height[mid] # min(凹槽左边高度, 凹槽右边高度) - 凹槽底部高度
w = i - st.top() - 1 # 凹槽右边的下标 - 凹槽左边的下标 - 1
class Solution:
    def trap(self, height: List[int]) -> int:
        stack = [0]
        res = 0
        for i in range(len(height)):
            if height[i]<height[stack[-1]]:
                stack.append(i)
            elif height[i] == height[stack[-1]]:
                stack.pop()
                stack.append(i)
            else:
                while stack and height[i] > height[stack[-1]]:
                    mh = height[stack[-1]]
                    stack.pop()
                    if stack:
                        rh = height[i]
                        lh = height[stack[-1]]
                        h = min(rh, lh) - mh
                        w = i - stack[-1] -1
                        res += h*w
            stack.append(i)
        return res

84.柱状图中最大的矩形

力扣链接
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。
在这里插入图片描述

思路1 双指针

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        size = len(heights)
        minleft = [0] * size
        minright = [0] * size
        
        # 记录每个柱子左边第一个矮子
        minleft[0] = -1# 防止死循环
        for i in range(size):
            t = i-1
            while t>=0 and heights[t]>=heights[i]: #不断向左寻找,没找到就尝试这个高柱子自己的次级柱子
                t = minleft[t]
            minleft[i] = t
        # 记录每个柱子右边第一个矮子
        minright[-1] = size
        for i in range(size-2, -1, -1):
            t = i+1
            while t<size and heights[t]>=heights[i]: #不断向右寻找,没找到就尝试这个高柱子自己的次级柱子
                t = minright[t]
            minright[i] = t
        
        res = 0
        for i in range(size):
            res1 = heights[i] * (minright[i] - minleft[i] - 1)
            res = max(res1,res)
        return res

思路2 单调栈

本题是要找每个柱子左右两边第一个小于该柱子的柱子,所以从栈头(元素从栈头弹出)到栈底的顺序应该是从大到小的顺序
在这里插入图片描述
逻辑和接雨水差不多,就是栈顶和栈顶的下一个元素以及要入栈的三个元素组成了我们要求最大面积的高度和宽度。

找每个柱子左右侧的第一个高度值小于该柱子的柱子
单调栈:栈顶到栈底:从大到小(每插入一个新的小数值时,都要弹出先前的大数值)
栈顶,栈顶的下一个元素,即将入栈的元素:这三个元素组成了最大面积的高度和宽度

有三种情况:
情况一:当前遍历的元素heights[i]大于栈顶元素heights[st.top()]的情况
情况二:当前遍历的元素heights[i]等于栈顶元素heights[st.top()]的情况
情况三:当前遍历的元素heights[i]小于栈顶元素heights[st.top()]的情况
此外,还需要在height首尾各加一个0,以防跳过

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        res = 0
        stack = [0]
        heights.insert(0,0)
        heights.append(0)
        for i in range(1, len(heights)):
            if heights[i] > heights[stack[-1]]:
                stack.append(i)
            elif heights[i] == heights[stack[-1]]:
                stack.pop()
                stack.append(i)
            else:
                while stack and heights[i] < heights[stack[-1]]:
                    mid = stack[-1]
                    stack.pop()
                    if stack:
                        left = stack[-1]
                        right = i
                        w = right - left - 1
                        h = heights[mid]
                        res = max(res, w * h)
                stack.append(i)
        return res

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

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

相关文章

【记录】IDEA2023的激活与安装

前言&#xff1a; 记录IDEA2023的激活与安装 第一步&#xff1a;官网下载安装包&#xff1a; 下载地址&#xff1a;https://www.jetbrains.com/idea/download/other.html 这个最好选择2023版本&#xff0c;用着很nice。 安装步骤就不详解了&#xff0c;无脑下一步就可以了…

09 - matlab m_map地学绘图工具基础函数 - 绘制区域填充、伪彩色、加载图像和绘制浮雕效果的有关函数

09 - matlab m_map地学绘图工具基础函数 - 绘制区域填充、伪彩色、加载图像和绘制浮雕效果的有关函数 0. 引言1. 关于m_pcolor2. 关于m_image3. 关于m_shadedrelief4. 关于m_hatch5. 结语 0. 引言 本篇介绍下m_map中区域填充函数&#xff08;m_hatch&#xff09;、绘制伪彩色图…

C++多态~~的两个特殊情况

目录 1.多态的概念 2.简单认识 &#xff08;1&#xff09;一个案例 &#xff08;2&#xff09;多态的两个满足条件 &#xff08;3&#xff09;虚函数的重写 &#xff08;4&#xff09;两个特殊情况 1.多态的概念 &#xff08;1&#xff09;多态就是多种形态&#xff1b; …

某腾X滑块验证码

⚠️前言⚠️ 本文仅用于学术交流。 学习探讨逆向知识,欢迎私信共享学习心得。 如有侵权,联系博主删除。 请勿商用,否则后果自负。 网址 aHR0cHM6Ly9jbG91ZC50ZW5jZW50LmNvbS9wcm9kdWN0L2NhcHRjaGE= 1. 先整体分析一下 1_1. 验证码信息下发接口 cap_union_prehandle ua:…

AI绘画工具Midjourney:和Discord互相成就

前言 提到文生图&#xff0c;很多人都会想到植根于根植于Discord社区的Midjourney&#xff0c;本篇文章就基于作者的使用体验思考&#xff0c;并结合了Discord来对Midjourney进行探讨&#xff0c;感兴趣的朋友一起来看看吧。 如果要说现在最火的文生图&#xff0c;不得不说到Mi…

openmetadata1.3.1 自定义连接器 开发教程

openmetadata自定义连接器开发教程 一、开发通用自定义连接器教程 官网教程链接&#xff1a; 1.https://docs.open-metadata.org/v1.3.x/connectors/custom-connectors 2.https://github.com/open-metadata/openmetadata-demo/tree/main/custom-connector &#xff08;一&…

本周波动预警!7月将一路上涨,牛市“复苏“?低于6万美元的比特币,是熊市陷阱吗?

比特币在第三季度伊始发出了一些积极信号。随着上周末的涨势&#xff0c;BTC/USD最高一度达到63818美元&#xff0c;这让人对比特币能否重拾牛市信心满怀希望。不过&#xff0c;在冲破关键阻力位64000美元之前&#xff0c;市场参与者仍保持谨慎态度。比特币要想维系开头的牛市态…

掌握React与TypeScript:从零开始绘制中国地图

最近我需要使用reactts绘制一个界面&#xff0c;里面需要以中国地图的形式展示区块链从2019-2024年这五年的备案以及注销情况&#xff0c;所以研究了一下这方面的工作&#xff0c;初步有了一些成果&#xff0c;所以现在做一些分享&#xff0c;希望对大家有帮助&#xff01; 在这…

使用Qt制作一个简单的界面

1、创建工程 步骤一&#xff1a; 步骤二&#xff1a; 步骤三&#xff1a; 选择 build system&#xff0c;有qmake、CMake 和 Qbs 三个选项。 CMake 很常用&#xff0c;功能也很强大&#xff0c;许多知名的项目都是用它&#xff0c;比如 OpenCV 和 VTK&#xff0c;但它的语法繁…

heic格式转化jpg如何操作?heic转jpg,分享6款图片转化器!

随着苹果iOS 11系统的推出&#xff0c;HEIC格式作为一种新的图片格式逐渐走进大众视野&#xff0c;heic格式在保证照片质量的同时&#xff0c;能显著减少系统存储空间的占用。然而&#xff0c;这也给非苹果用户带来了一些困扰&#xff0c;因为HEIC格式的图片在Windows系统上并不…

深入理解C# log4Net日志框架:功能、使用方法与性能优势

文章目录 1、log4Net的主要特性2、log4Net框架详解配置日志级别 3、log4Net的使用示例4、性能优化与对比5、总结与展望 在软件开发过程中&#xff0c;日志记录是一个不可或缺的功能。它可以帮助开发者追踪错误、监控应用程序性能&#xff0c;以及进行调试。在C#生态系统中&…

探秘 Django 专业之道

一、Django项目开发 1.web框架底层 1.1 网络通信 注意&#xff1a;局域网 个人一般写程序&#xff0c;想要让别人访问&#xff1a;阿里云、腾讯云。 去云平台租服务器&#xff08;含公网IP&#xff09;程序放在云服务器 先以局域网为例 我的电脑【服务端】 import sock…

无法访问指向的web服务器(或虚拟主机)的目录,请检查网络设置

微信公众平台,进行业务域名、JS接口安全域名、网页授权域名配置时&#xff0c;遇到的问题中有&#xff1a;无法访问指向的web服务器&#xff08;或虚拟主机&#xff09;的目录&#xff0c;请检查网络设置&#xff0c;这里简单记录一下处理过程。 关于这个问题首先保证下载…

基于PHP技术的校园论坛设计的设计与实现08586

基于PHP技术的校园论坛设计的设计与实现 摘 要 本项目旨在基于PHP技术设计与实现一个校园论坛系统&#xff0c;以提供一个功能丰富、用户友好的交流平台。该论坛系统将包括用户注册与登录、帖子发布与回复、个人信息管理等基本功能&#xff0c;并结合社交化特点&#xff0c;增强…

2023软考中级《软件设计师》(备考冲刺版) | 数据库系统

目录 1.数据库的基本概念 1.1 数据库体系结构 1.2 三级模式结构 1.3 数据仓库 2.数据库设计过程 2.1 概念结构设计 2.1.1 概念设计过程 2.1.2 E-R图 2.2 逻辑结构设计 2.2.1 关系模式相关概念 2.2.2 E-R图转关系模式&#xff08;涉及下午题&#xff09; 2.2.3 关系…

SysML与MBSE的关系

SysML与MBSE的关系 对于任何基于模型的系统工程 &#xff08;MBSE&#xff09; 方法&#xff0c;推荐的最佳实践是基于模型的语言、基于模型的工具、基于模型的流程和基于模型的架构框架的协同应用&#xff0c;如下图所示 系统架构四元组 图。经过十年将SysML应用于棘手的系统…

海思NNIE部署yolov5-shufflenet

1.简要说明 由于NNIE上transpose支持的顺序是固定的,shufflenet那种x=torch.transpose(x,1,2).contiguous() 的操作一般是不支持的。需要进行调整。 2.使用工程以及修改 使用的是开源工程:GitHub - Lufei-github/shufflev2-yolov5: shufflev2-yolov5:lighter, faster and ea…

基于“香港世界”的SLAM技术介绍

在视觉感知技术中&#xff0c;理解和描述复杂的三维室外场景至关重要&#xff0c;尤其是自动驾驶技术的发展要求对陌生环境具有更强的适应能力和鲁棒性。传统上&#xff0c;使用“曼哈顿世界”和“亚特兰大世界”模型来描述具有垂直和水平结构的城市场景。 当遇到像香港这样地形…

python爬虫之scrapy框架基本使用

python爬虫之scrapy框架基本使用 1、环境安装&#xff1a;pip install scrapy 2、创建一个工程&#xff1a;scrapy startproject xxxPro 3、cd xxxPro 4、在spiders子目录中创建一个爬虫文件&#xff1a;scrapy genspider spiderName www.xxx.com 5、执行工程&#xff1a;scra…

当年很多跑到美加澳写代码的人现在又移回香港?什么原因?

当年很多跑到美加澳写代码的人现在又移回香港&#xff1f;什么原因&#xff1f; 近年来&#xff0c;确实有部分曾经移民到美国、加拿大、澳大利亚等地的香港居民选择移回香港。这一现象与多种因素相关&#xff0c;主要可以归结为以下几点&#xff1a; 疫情后的环境变化&#…