代码随想录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  = 0leftmax = [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 += Heightreturn 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 = 0stack = []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] - 1res += h * wstack.append(i)return res

84. 柱状图中最大的矩形

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

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

2,2,34,5,4,33

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

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

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

解法一:双指针

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

        leftminidx[0] = -1for 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 = 0leftminidx = [0] * len(heights)rightminidx = [0] * len(heights)leftminidx[0] = -1for i in range(1, len(heights)):t = i - 1  # i左边的索引while t >= 0 and heights[i] <= heights[t]:t = leftminidx[t]leftminidx[i] = trightminidx[len(heights)-1] = len(heights)for i in range(len(heights)-2, -1, -1):t = i + 1while 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 = 0stack = []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.rhkb.cn/news/422878.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

随手记:uniapp小程序登录方式和小程序使用验证码登录

小程序登录方式&#xff1a; 方式一&#xff1a;小程序授权登录 通过uni.login获取 临时登录凭证code&#xff0c;向后端换取token。 <u-button type"primary" shape"circle" click"login">登 录</u-button>login() {uni.login({p…

深入探索 Ubuntu:从基础到高级应用

本文深入探讨了 Ubuntu 操作系统&#xff0c;涵盖了其起源与发展、安装与配置、软件管理、系统优化、网络配置、安全防护以及在不同领域的应用等多个方面。 在起源与发展部分&#xff0c;介绍了 Ubuntu 于 2004 年创立的背景以及其版本的演进。安装与配置环节详细阐述了系统安…

【练习10】链表相加

链接&#xff1a;链表相加(二)_牛客题霸_牛客网 (nowcoder.com) 分析&#xff1a; 算法原理是逆序高精度算法 逆序的原因是为了实现从低位&#xff08;个位&#xff09;开始相加。 public class Solution {//逆序链表public ListNode reverse(ListNode head){ListNode newHead …

动态规划的解题思想

1. 从斐波那契数列说起 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c; &#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0, F(2) 1 F&#xff08;n&#xff09; F&…

机器学习--卷积神经网络(包括python实现)

卷积神经网络 1. 计算方法 &#xff08;1&#xff09;输入和输出channel 1时 首先我们要知道channel是什么意思&#xff0c;顾名思义channel就是“通道”的意思qwq。我们来举个例子&#xff0c;在计算机视觉中&#xff0c;如果一张图片是黑白的&#xff0c;那么每个像素点都…

Linux中使用Docker构建Nginx容器完整教程

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f427;Linux基础知识(初学)&#xff1a;点击&#xff01; &#x1f427;Linux高级管理防护和群集专栏&#xff1a;点击&#xff01; &#x1f510;Linux中firewalld防火墙&#xff1a;点击&#xff01; ⏰️创作…

JD18年秋招笔试疯狂数列python解答

问题如下&#xff1a; 链接&#xff1a;疯狂序列_京东笔试题_牛客网 [编程题]疯狂序列 热度指数&#xff1a;149 时间限制&#xff1a;C/C 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C 32M&#xff0c;其他语言64M 东东从京京那里了解到有一个无限长的数字序列: 1…

uniapp 做一个查看图片的组件,图片可缩放移动

因为是手机端&#xff0c;所以需要触摸可移动&#xff0c;双指放大缩小。 首先在components里建个组件 查看图片使用 uni-popup 弹窗 要注意 transform的translate和scale属性在同一标签上不会一起生效 移动就根据触摸效果进行偏移图片 缩放就根据双指距离的变大变小进行缩…

DFS算法专题(二)——穷举vs暴搜vs深搜vs回溯vs剪枝【OF决策树】

目录 1、决策树 2、算法实战应用【leetcode】 2.1 题一&#xff1a;全排列 2.2.1 算法原理 2.2.2 算法代码 2.2 题二&#xff1a;子集 2.2.1 算法原理【策略一】 2.2.2 算法代码【策略一】 2.2.3 算法原理【策略二&#xff0c;推荐】 2.2.4 算法代码【策略二&#x…

浅谈基于负荷时空均衡和弹性响应的电动汽车快充电价定价策略

摘要&#xff1a;为了引导电动汽车有序充电&#xff0c;提出了一种考虑负荷时空均衡和弹性响应的电动汽车快充电价定价策略。引入交通流理论描述交通路网&#xff0c;建立电动汽车快充负荷时空分布模型&#xff1b;考虑配电网调度和电动汽车快充负荷的弹性需求&#xff0c;构建…

React Native 0.76,New Architecture 将成为默认模式,全新的 RN 来了

关于 React Native 的 New Architecture 概念&#xff0c;最早应该是从 2018 年 RN 团队决定重写大量底层实现开始&#xff0c;因为那时候 React Native 面临各种结构问题和性能瓶颈&#xff0c;最终迫使 RN 团队开始进行重构。 而从 React Native 0.68 开始&#xff0c;New A…

轻松搞定Arduino开发环境,像玩积木一样简单!

朋友们,有没有人和我一样,曾经对Arduino望而却步?说到“开发环境”这几个字,感觉脑子就要爆炸了,光是想象安装各种软件、调试环境就能把人吓跑。相信我,我也曾有过这样的感觉。但是,当我真正开始玩Arduino后,我发现一切都不像想象中那么复杂!其实,搭建Arduino开发环境…

光耦合器的工作原理和故障诊断

光耦合器&#xff0c;也称为光隔离器&#xff0c;是现代电子设备中必不可少的组件&#xff0c;尤其是在确保系统不同部分之间的电气隔离方面。它们通过使用光传输信号来防止高压或不需要的信号影响敏感组件。在本文中&#xff0c;我们将讨论光耦合器的工作原理、故障诊断和识别…

安泰功率放大器有哪些特点呢

功率放大器是电子设备中的重要组成部分&#xff0c;其作用是将输入信号的电功率放大到足够的水平&#xff0c;以驱动负载&#xff0c;如扬声器或天线。功率放大器有一些独特的特点&#xff0c;这些特点对于各种应用至关重要。下面将详细介绍功率放大器的特点&#xff0c;以更好…

Unity教程(十五)敌人战斗状态的实现

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…

前端JS必用工具【js-tool-big-box】学习,获取全球热点城市当前时间、时区以及令时

js-tool-big-box工具库&#xff0c;之前也添加了几个热点城市的当前时间显示&#xff0c;但当时城市较少&#xff0c;功能也比较简单&#xff0c;只是显示了时分秒。 最近有使用者说&#xff0c;光有时分秒&#xff0c;功能太少&#xff0c;所以对js-tool-big-box工具库做了改进…

windows vscode ssh 连接远程服务器

1.在 PowerShell 中运行以下命令&#xff0c;查看 OpenSSH 客户端是否已安装 Get-WindowsCapability -Online | Where-Object Name -like OpenSSH.Client*如果有安装的话&#xff0c;如下图 2.如果没有安装&#xff0c;那么用下面的命令进行安装 Get-WindowsCapability -On…

科研绘图系列:R语言宏基因组PCoA图(PCoA plot)

介绍 PCoA(主坐标分析,也称为主轴分析)是一种多维统计技术,用于分析和可视化高维数据集,如宏基因组数据。在宏基因组学中,PCoA图用于展示样本之间的相似性和差异性,通常基于样本之间的距离或相似度矩阵。PCoA图说明: 样本间关系:PCoA图通过降维技术将高维数据投影到二…

(不用互三)AI绘画工具大比拼:Midjourney VS Stable Diffusion该如何选择?

文章目录 &#x1f4af;如何选择合适的AI绘画工具根据个人需求选择1. 您喜欢什么风格的绘画&#xff1f;2. 您想要创作什么主题的内容&#xff1f;3. 您对绘画工具的使用经验如何&#xff1f; 比较工具特点1. 工具的易用性和功能性如何&#xff1f;易用性&#xff1a;功能性&am…

【机器学习】分类与回归——掌握两大核心算法的区别与应用

【机器学习】分类与回归——掌握两大核心算法的区别与应用 1. 引言 在机器学习中&#xff0c;分类和回归是两大核心算法。它们广泛应用于不同类型的预测问题。分类用于离散的输出&#xff0c;如预测图像中的对象类型&#xff0c;而回归则用于连续输出&#xff0c;如预测房价。…