算法题 — 接雨水

devtools/2024/10/21 3:35:12/

给定 n 给非负整数,表示每个宽度为 1 的柱子的高度图,计算按照此排列的柱子,下雨之后能能接到多少雨水。

数组

输入:height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]

输出:6

解释:上面是由数组 [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1] 表示的高度图,在这种情况袭,可以接住 6 个单位雨水(蓝色部分表示雨水)。

就是用一个数组表示一个条形图,问这个条形图最多能接多少水。

1 暴力解法

具体来讲,对于位置 i 能装下多少水呢?

数组

能装下 2 格。为什么呢?因为位置 i 处能达到的水柱的高度和其左边的最高柱子、右边的最高柱子有关。其左边最高柱子的高度是 2,其右边最高柱子的高度是 3,因为 height[i] 的高度是 0,所以位置 i 处能装下 2 格的水。

这里我们假设左右两个最高柱子的高度分别为 leftMax 和 rightMax,位置 i 处的水柱高度就是 min(leftMax, rightMax) - height[i]。

根据以上的思路:

fun trap(height: Array<Int>): Int {val n = height.sizevar res = 0// 位置 0 和位置 n - 1 处无法存储水for (i in 1 until n - 1) {var leftMax = 0 // 位置 i 处左边最高的柱子var rightMax = 0 // 位置 i 处右边最高的柱子// 寻找左边最高的柱子,这里到 i 是因为后面要 -height[i]for (j in 0..i) {leftMax = leftMax.coerceAtLeast(height[j])}// 寻找右边最高的柱子,这里从 i 开始是因为后面要 -height[i]for (j in i until n) {rightMax = rightMax.coerceAtLeast(height[j])}res += leftMax.coerceAtMost(rightMax) - height[i]}return res
}
2 备忘录优化

在暴力算法中,需要计算每个位置的 leftMax 和 rightMax,我们可以直接先把结果计算出来,不需要每次都遍历。

定义两个数组 leftMax 和 rightMax 充当备忘录,leftMax[i] 表示位置 i 左边最高的柱子高度,rightMax[i] 表示位置 i 右边最高的柱子高度。预先把这两个数组准备好,避免重复计算:

fun trap(height: Array<Int>): Int {val n = height.sizevar res = 0// 数组备忘录val leftMax = IntArray(n)val rightMax = IntArray(n)// 初始化leftMax[0] = height[0]rightMax[n - 1] = height[n - 1]for (i in 1 until n) {leftMax[i] = height[i].coerceAtLeast(leftMax[i - 1])}for (i in n - 2 downTo 0) {rightMax[i] = height[i].coerceAtLeast(rightMax[i + 1])}for (i in 1 until n - 1) {res += leftMax[i].coerceAtMost(rightMax[i]) - height[i]}return res
}

备忘录算法和暴力算法的思路差不多,就是避免了重复计算。

4 双指针解法
fun trap(height: Array<Int>): Int {val n = height.sizevar res = 0var left = 0var right = n - 1// 左边最高柱子的高度和右边最高柱子的高度var leftMax = height[0]var rightMax = height[n - 1]while (left < right) {leftMax = leftMax.coerceAtLeast(height[left])rightMax = rightMax.coerceAtLeast(height[right])if (leftMax < rightMax) { // 左边的柱子低于右边柱子的高度,水的高度只和较低的柱子有关res += leftMax - height[left]left++} else { // 右边的柱子低于左边柱子的高度,水的高度只和较低的柱子有关res += rightMax - height[right]right--}}return res
}

http://www.ppmy.cn/devtools/56256.html

相关文章

GPT-5 一年半后发布?对此你有何期待?

GPT-5技术突破预测 GPT-5预计将在算法和理解力方面带来重大突破。在算法方面&#xff0c;GPT-5可能会采用更先进的深度学习技术和优化算法&#xff0c;以提高模型的训练效率和性能。此外&#xff0c;GPT-5可能会引入更多的先验知识和结构化信息&#xff0c;以提高模型的语言理…

MySQL 重新初始化实例

1、关闭mysql服务 service mysqld stop 2、清理datadir(本例中指定的是/var/lib/mysql)指定的目录下的文件&#xff0c;将该目录下的所有文件删除或移动至其他位置 cd /var/lib/mysql mv * /opt/mysql_back/ 3、初始化实例 /usr/local/mysql/bin/mysqld --initialize --u…

Docker(六)-本地镜像发布到私有库

1.下载镜像Docker Registry 用于搭建私人版本Docker Hub docker pull registry2.运行私有库Registry 运行私有库Registry&#xff0c;相当于本地有个私有Docker hubdocker run -d -p hostPort:containerPort -v 【宿主机目录】:【容器目录】 --privilegedtrue 【私有库镜像】…

为什么要使用多线程(并发编程)

目录 1.上下文的切换 1.1 什么是上下文切换 2. 并发编程的死锁问题 2.1 死锁产生的原因 2.2 避免死锁的方法 3.资源限制的挑战3.1 什么是资源限制 并发编程的目的是为了让程序更快&#xff0c;大家都知道并不是开启的线程越多越快&#xff0c;因为开启的线程越多随即面临…

LinkedIn被封原因和解封方法

对于初识领英和对领英生态规则不熟悉的人来说&#xff0c;很容易造成领英账号被封号(被限制登录)的情况&#xff0c;那么如何才能避免和解决领英帐号被封号(被限制登录)的难题呢&#xff1f; 领英帐号被封号或被限制登录主要会有两类情况。 首先要搞清楚&#xff0c; Linkedi…

jsonata工具查询JSON和转换

jsonata工具查询JSON和转换 参考网址&#xff1a;http://docs.jsonata.org/1.7.0/date-time https://github.com/IBM/JSONata4Java 简介 JSONata是IBM的OPen Source项目&#xff0c;正是这样做的。它是一种用于查询和转换 JSON 数据结构的表达式语言。JSONata 是一种用于查询…

ubuntu server 24.04 使用记录

我安装 Ubuntu server 24.04 选择了 minimal 方式&#xff0c;发现不知道是忘记选了还是怎样&#xff0c;ssh 无法登录。 本来以为 24.04 上只会遇到和 22.04 上一样的问题&#xff0c;校网需要验证。经过几周分析研究&#xff0c;终于摸清楚了校网验证过程&#xff0c;然后写…

数据分析三剑客-Matplotlib

数据分析三剑客 数据分析三剑客通常指的是在Python数据分析领域中&#xff0c;三个非常重要的工具和库&#xff1a;Pandas、NumPy和Matplotlib。Pandas主要负责数据处理和分析&#xff0c;NumPy专注于数值计算和数学运算&#xff0c;而Matplotlib则负责数据可视化。这三个库相…