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

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

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

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

相关文章

WMS、ERP、MES之间的关系

WMS&#xff08;仓库管理系统&#xff09;、ERP&#xff08;企业资源计划&#xff09;、MES&#xff08;制造执行系统&#xff09;是企业管理和运作中常见的三种系统&#xff0c;它们在不同的层面上发挥作用&#xff0c;但之间又有紧密的联系。三者之间的区别如下&#xff1a; …

【哈哈大一上学的全忘了,重开!!】STM32从零入门物联网开发

本笔记资料来源 &#xff1a;STM32物联网入门30步&#xff1d;单片机物联网入门教程 WIFI连接阿里云物联网CubeMXHAL库蓝牙ESP8266杜洋主讲_哔哩哔哩_bilibili IOT&#xff1a;Internet of things 学习目标&#xff1a; 1.掌握洋桃IoT开发板的各功能以及驱动与基本应用 2.掌…

【C++11:右值引用,列表初始化】

统一列表初始化&#xff1a; 构造函数的函数名与函数体之间增加一个列表&#xff0c;用于对成员初始化 在实例化对象时&#xff0c;支持单/多参数的隐式转化&#xff0c;同时也可以省略符号&#xff0c;让代码更简洁 右值的引用 左值&#xff1a; 左值与右值的重要区别就是能…

tkinter显示图片

tkinter显示图片 效果代码解析打开和显示图像 代码 效果 代码解析 打开和显示图像 def open_image():file_path filedialog.askopenfilename(title"选择图片", filetypes(("PNG文件", "*.png"), ("JPEG文件", "*.jpg;*.jpeg&q…

专题五:Spring源码之初始化容器上下文

上一篇我们通过如下一段基础代码作为切入点&#xff0c;最终找到核心的处理是refresh方法&#xff0c;从今天开始正式进入refresh方法的解读。 public class Main {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(…

2.3章节Python中的数值类型

1.整型数值 2.浮点型数值 3.复数   Python中的数值类型清晰且丰富&#xff0c;主要分为以下几种类型&#xff0c;每种类型都有其特定的用途和特性。 一、整型数值 1.定义&#xff1a;整数类型用于表示整数值&#xff0c;如1、-5、100等。 2.特点&#xff1a; Python 3中的…

面试题-Spring家族与SpringIOC

1.spring家族的介绍 Spring简单图&#xff1a; 2.IOC原理 IOC就是原先代码里需要开发者实现对象的创建和关系依赖&#xff0c;反转交给SpringIOC容器管理对象的生命周期和对象之间的依赖关系。 依赖注入的方式&#xff1a; Setter&#xff1a;实现特定属性的public sette…

RedHat9 | podman容器-续集

一、管理容器存储和网络资源 使用容器来运行简单的进程&#xff0c;然后退出。可以配置容连续运行特定服务&#xff0c;如数据库服务。如果持续运行服务&#xff0c;需要向容器添加更多的资源&#xff0c;如持久存储或对其他网络的访问权限。 针对企业容器平台上的大型部署&a…

数据资产安全策略的定制化之道:深入了解各企业独特需求,量身打造个性化的数据资产保护方案,确保数据安全无虞,助力企业稳健发展

目录 一、引言 二、企业数据资产安全现状分析 &#xff08;一&#xff09;数据安全风险多样化 &#xff08;二&#xff09;传统安全措施难以满足需求 &#xff08;三&#xff09;企业数据资产安全意识亟待提高 三、定制化数据资产安全策略的重要性 &#xff08;一&#…

SuperMap GIS基础产品FAQ集锦(20240701)

一、SuperMap iDesktopX 问题1&#xff1a;对于数据提供方提供的osgb格式的数据&#xff0c;如何只让他生成一个s3mb文件呢&#xff1f;我用倾斜入库的方式会生成好多个s3mb缓存文件 11.1.1 【解决办法】不能控制入库后只生成一个s3mb文件&#xff1b;可以在倾斜入库的时候设…

永磁同步电机离线参数识别

引言 永磁同步电机&#xff08;PMSM&#xff09;因其结构简单、功率密度高、转矩惯量比大和效率高等优点&#xff0c;在工业生产、航空航天和新能源交通等领域得到了广泛应用。然而&#xff0c;传统的参数辨识方法依赖位置传感器&#xff0c;这不仅增加了硬件成本&#xff0c;…

如何借用物联网快速实现高标准农田信息化

如何借用物联网快速实现高标准农田信息化 高标准农田信息化&#xff0c;作为现代农业发展的重要基石&#xff0c;是指在建设高产、稳产、节水、环保的农田基础上&#xff0c;深度融合现代信息技术&#xff0c;实现农田管理的精准化、智能化和高效化。物联网&#xff08;Intern…

sql server启动、连接 与 navicat连接sql server

一、sql server 启动 1.搜索cmd->以管理员身份运行 2.输入以下命令 net start mssqlserver 3.服务器启动成功 二、sql server连接 1.打开ssms&#xff0c;输入&#xff0c;连接 2.右键&#xff0c;属性 3.连接&#xff0c;勾选允许远程连接到此服务器 三、navicat连接sq…

20人团队如何免费使用 Atlassian 云产品?

企业赚钱越来越难&#xff0c;尤其是初创团队或小型团队更倾向于使用免费工具支持业务。团队规模影响协作复杂度&#xff0c;Atlassian 考虑到小团队的需求&#xff0c;提供了多种选择。比如&#xff0c;Jira 和 Confluence 的云版本有免费版&#xff0c;包含基本的项目管理功能…

三坐标测量机:柔性生产制造中的高精度测量解决方案

柔性生产制造是制造业的核心竞争力之一。它强调生产线的灵活性和适应性&#xff0c;以满足市场对产品多样化和个性化的需求。在当今快速变化的工业环境中&#xff0c;随着消费者对产品个性化和定制化需求的增加&#xff0c;柔性生产制造和三坐标测量机的结合&#xff0c;为智能…

MSVCR120.DLL丢失的多种修复方法,助你快速解决dll问题

在日常生活和工作中&#xff0c;电脑已经成为我们不可或缺的工具。然而&#xff0c;在使用电脑的过程中&#xff0c;我们常常会遇到一些问题&#xff0c;其中之一就是电脑运行软件时提示找不到msvcr120.dll。如果该文件缺失或损坏&#xff0c;可能会导致依赖它的应用程序无法启…

大聪明教你学Java | 深入浅出聊 RocketMQ

前言 &#x1f34a;作者简介&#xff1a; 不肯过江东丶&#xff0c;一个来自二线城市的程序员&#xff0c;致力于用“猥琐”办法解决繁琐问题&#xff0c;让复杂的问题变得通俗易懂。 &#x1f34a;支持作者&#xff1a; 点赞&#x1f44d;、关注&#x1f496;、留言&#x1f4…

一、课程介绍,基础—环境安装、判断、循环语句等(爬虫及数据可视化)

一、课程介绍&#xff0c;基础—环境安装、判断、循环语句等&#xff08;爬虫及数据可视化&#xff09; 1. 课程介绍1.1 相关内容1.2 学习目标1.3 学习内容安排 2. python2.1 环境配置2.2 标识符和关键字2.3 运算符2.4 判断语句2.5 循环语句 1. 课程介绍 1.1 相关内容 10天的…

Node.js安装及配置

文章目录 1.安装Node.js2.创建目录3.配置环境变量4.配置全局安装路径和缓存路径(可选)配置Webstorm 1.安装Node.js https://registry.npmmirror.com/binary.html?pathnode 推荐安装18.x版本 2.创建目录 下载解压后进入目录&#xff0c;创建node_global和node_cache两个空文…

AI播客下载:Practical AI(人工智能最新进展)

Practical AI这是由 http://Changelog.com推出的节目。Changelog 本身做了许多跟软件开发的 podcast 节目 。比如《The Changelog》播客 &#xff0c;这是一个专注于软件领域的播客&#xff0c;每周一发布最新新闻摘要&#xff0c;周三进行深入技术访谈&#xff0c;周五则是访谈…