机试打卡 -05 接雨水(动态规划栈)

news/2024/10/18 7:58:34/

 


我的思路:依次计算每一列能接收的雨水量。
 

关键点:如何计算得到每一列所能接收到的雨水量?

        某一列能够接收到的雨水量,取决于其左右两侧最高的柱子。仅有当左右两侧的柱子均高于该列的高度,该列才可收到雨水,其雨水量为 min( left_height-h , right_height-h) 。

class Solution:def trap(self, height: List[int]) -> int:# height数组->对象属性self.height=heightself.height_len=len(height)# 哈希表存储上一时刻的left_height与right_heightHash=dict()Hash['left_height']=0Hash['right_height']=max(height)self.Hash=Hash# rain_sum:总雨水量rain_sum=0# 依次计算每一个柱子所能接水的高度# i为索引for i in range(len(height)):# 传入柱子的索引rain_sum+=self.rain_calculate(i)return rain_sumdef rain_calculate(self,index):# 取自身高度hh=self.height[index]# 左侧高度if index:left_height=max(self.Hash['left_height'],self.height[index-1])else:left_height=0# 右侧高度if self.height[index]!=self.Hash['right_height']:right_height=self.Hash['right_height']else:if index==self.height_len-1:right_height=0else:seq_temp=self.height[index+1:self.height_len]right_height=max(seq_temp)# 更新哈希表self.Hash['left_height']=left_heightself.Hash['right_height']=right_height# 仅有当left_height和right_height均高于h时,该列才可接收到雨水if left_height>h and right_height>h:return min(left_height-h,right_height-h)else:return 0

关键点:哈希表存储上一时刻的left_height与right_height

为什么需要存储上一时刻的left_height与right_height?

        数组从左往右遍历,新柱子的 left_height 直接取 max(前一个柱子的left_height , 前一个柱子的高度),有些类似递归的思想。

        新柱子的 right_height 则分为两种情况,一种是 新柱子的高度不等于前一个柱子的 right_height,这种情况下则令新柱子的 right_height 直接取 前一个柱子的 right_height 即可;另一种情况则是 新柱子的高度等于前一个柱子的 right_height,即说明前一个柱子的 right_height 可能取自该根柱子,则新柱子的 right_height 取后面的柱子的最大值(数组切片) 即可。


思路2:动态规划

动态规划 - 复杂度分析

时间复杂度为:O(n)

空间复杂度为:O(n)


思路3:单调栈

class Solution:def trap(self, height: List[int]) -> int:ans = 0# 建立单调递减栈,用列表存储stack = list()# 从左向右依次遍历for i, h in enumerate(height):# 当栈不为空且h大于栈顶的高度时,进入while循环while stack and h > height[stack[-1]]:# 取出栈顶元素,作为低洼top = stack.pop()# 若取出栈顶元素后栈为空,则跳出while循环if not stack:break# left为左边界的索引,i为右边界的索引left = stack[-1]currWidth = i - left - 1currHeight = min(height[left], height[i]) - height[top]ans += currWidth * currHeight# 循环结束后,将i加入栈中stack.append(i)return ans

关键点:单调递减栈

        考虑到低洼(可接雨水)必须有左右两侧边界,所以用python列表建立单调递减栈。当出现某一根柱子大于栈顶元素的高度时,开始进入内循环。出栈的top为低洼,根据left和right边界索引计算雨水存量,直到下一个栈顶大于等于h,方可跳出内循环。最后一定要将 i 入栈,因为 i 仍可能可以构成某一个低洼的左边界。


http://www.ppmy.cn/news/79755.html

相关文章

数组题目总结 -- 花式遍历

目录 一. 反转字符串中的单词思路和代码:I. 博主的做法II. 东哥的做法III. 其他做法1IV. 其他做法2 二. 旋转图像思路和代码:I. 博主的做法II. 东哥的做法 三. 旋转图像(逆时针旋转90)思路和代码:I. 博主和东哥的做法 …

es 二、核心概念

目录 Nrt cluster集群概念 node节点 Document 文档 Index 索引 Field字段 Type 类型 shard分片 Replica shard副本 数据库和es概念对比 Nrt 写入一秒后就能搜到 cluster集群概念 一台机器启动一个实例即可,多个组成 node节点 一个实例一个节点 Documen…

深度学习基础篇之卷积神经网络(CNN)

一、CNN的基本结构 首先我们来看CNN的解百纳结构,一个常见的图像识别CNN模型如下图: 从图中可以看出最左边的图像就是模型的输入层,在计算机中就是若干个矩阵,这点与DNN类似。 接着是卷积层(Convolution Layer&…

【正点原子STM32连载】 第十六章 外部中断实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

1)实验平台:正点原子stm32f103战舰开发板V4 2)平台购买地址:https://detail.tmall.com/item.htm?id609294757420 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第十六…

C++ new和delete详解

文章目录 1、 C C C内存分布2、 C C C内存管理方式3、 n e w new new 和 d e l e t e delete delete 底层实现4、定位 n e w new new表达式(了解)5、 m a l l o c 、 f r e e 和 n e w 、 d e l e t e malloc、free和new、delete malloc、free和new、de…

Java学习路线(11)——常用API

一、Object与Objects Object 概念: Java对象的总类。 方法: 方法说明String toString()默认返回当前对象在堆内存中的地址:类全名内存地址Boolean equals(Object o)比较对象的地址是否相同 toString() StudentExtend student new Stude…

数据结构与算法:树形查找

一.二叉排序树&#xff08;BST&#xff09; 1.个人理解 左子树结点值 < 根结点值 < 右子树结点值对二叉排序树进行中序遍历&#xff0c;可以得到一个递增的有序数列 2.二叉树查找 原理&#xff1a; 对于一个给定的二叉排序树&#xff0c;如果要查找一个节点&#xff0…

安卓开发投屏反控实现方式

在安卓开发中&#xff0c;可以通过MediaProjection API来实现屏幕投屏的功能&#xff0c;同时也可以通过Socket通信实现反控功能。下面将详细介绍实现步骤和注意事项。 1. 创建MediaProjectionManager对象 首先&#xff0c;我们需要创建一个MediaProjectionManager对象&#…