前言:
作者简介:大家好,我是翼同学!
个人主页:翼同学的CSDN博客
系列专栏:【Leetcode】刷题与总结
备注:如果文章有误,请指正,万分感谢!让我们一起学习,一起进步。
✅最后:如果文章对您有帮助,请三连支持一下博主哦。
今天在Leetcode上刷题,看到一道题很有趣。我乍一看,没有思路,但是仔细想了想,还是没思路。。。。哈哈,开个玩笑。
当我写出后解法后,系统老是提醒超出时间限制,太难了,努力想了好久,优化解法后终于通过了!还挺有成就感。
后来在官方的解法中,我又学到了其他的解题方法,解题的思路非常棒,所以就有了这篇文章,想和大家分享一下。
✨描述:
给定一个数组
height
,数组里有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 个单位的雨水(蓝色部分表示雨水)
- 刚开始我的想法是,只要求出每一列上能存放的雨水量,再加起来就行
- 需要注意的是,最两端的柱子是不用考虑的,因为也不可能有雨水
- 下面举两个例子来解释一下我的思路
由上图可知,若想求A列上的雨水,则可发现:
A
两侧最高的列分别是B
和C
- 显然
B
比C
矮- 那么
A
上接到的雨水量为B-A
- 也就是说,
A
上的雨水量为2
举例二:
由上图可知,若想求A列上的雨水,则可发现:
A
两侧最高的列分别是B
和C
- 显然
B
比C
矮- 但是此时的
B
比A
还要矮- 那么
A
上并不能接到雨水
总结:
我们可以对每一列上的雨水量进行计算(最两端的柱子不考虑),最后相加即可。
需要遍历数组,对每一列A的左右两侧B
,C
中,取出较矮的那一列,减去A
列的高度就能求出A
上接到的雨水量(如例子一)
但是如果B,C
较矮的那一列比A
还要矮,那么A
上就没有雨水。(如例子二)
代码
这是刚开始我写的代码:
但是超出了时间限制:
虽然这个思路不错,但是太耗时间了,通过不了。
那怎样能减低时间复杂度?
当我们分析后发现,上述代码之所以时间复杂度高,是因为对于计算每一列上的雨水量,都必须向两边寻找最大值,这就很耗费时间。
但是,我们可以利用动态规划,先知道每个位置的两侧的最大值是多少,那么就能够更加快速的求出接到的雨水量。也就是说,提前储存每个位置上左边所有柱子中的最大值,以及右边所有柱子中的最大值。
这该如何实现呢?
思路如下:
- 我们可以定义两个数组
B
和C
- 当
1 <= i <= n-1
时,在B[i]
表示下标i
及其i
左边的柱子中的最大值- 正向遍历数组
height
,得到B[]
- 当
0 <= j <= n-2
时,在C[j]
表示下标j
及其j
右边的柱子中的最大值- 反向遍历数组
height
,得到C[]
- 最后遍历数组
height
,对于每个柱子,计算接到的雨水值,和之前那个超时的算法差不多。
很幸运!通过了。
那么问题来了,还能想到什么解法呢?
想了很久后,思路二出现了。
看下图:
所以整理一下思路
写出代码如下:
通过了!
接下来,我们来欣赏一下其他超棒的解法!
思路三是利用单调栈的思想。
下面是来自LeetCode官方题解:
代码实现如下:
思路四是利用双指针的思想。
同样也是官方的解法。
具体如下:
说实话,遇到这道很坏很坏的题,确实体会到很多,其中一点就是我好菜。。。
随着刷题次数增加后,当我回过头来看今天记录的这道难题,希望能够更加轻松,彻底的理解与掌握。
对于这道题,你有什么想法呢,欢迎到评论区一起讨论,分享你的解法吧!!!