42.接雨水
https://leetcode-cn.com/problems/trapping-rain-water
题目描述
方法 1:暴力法
思路
如果一根柱子的左右两边有比它高的柱子的话,那这根柱子的位置就可以储存雨水,所以问题可以细化成:
每根柱子所在的位置可以储存多少雨水
要求这个问题的答案,只需分别找到这根柱子左右两侧出现的最高的柱子,取两者中较短的那根,减去当前柱子的高度,就是这个位置所能储存的雨水量了。
复杂度分析
时间复杂度:$O(N^2)$,N 为数组长度,遍历数组求每根柱子的位置所能储存的雨水量是 $O(N)$,对于每根柱子,要分别向左和向右遍历找出最高的柱子,时间复杂度是 $O(N)$,所以总的时间复杂度是 $O(N^2)$。
空间复杂度:$O(1)$。
代码
JavaScript Code
方法 2:空间换时间
思路
在方法 1 中,我们是分别寻找每根柱子左右两侧最高的柱子,时间复杂度是 $O(N^2)$。
但其实可以用空间换时间,先遍历一遍数组,记录下每根柱子左右最高的柱子分别是哪根。
复杂度分析
时间复杂度:$O(N)$,N 为数组长度,遍历一遍记录每根柱子左侧的最高柱子为 $O(N)$,遍历一遍记录每根柱子右侧的最高柱子为 $O(N)$,遍历一遍计算每根柱子位置能储存的雨水量为 $O(N)$,即 $O(3N)$,忽略常数,也就是 $O(N)$。
空间复杂度:$O(N)$,N 为数组长度,使用了两个数组来记录左右侧最高柱子,空间复杂度提高到了 $O(N)$。
代码
JavaScript Code
方法 3:双指针
思路
方法 2 使用了两个数组来记录左右侧的最高柱子,实际上,我们可以改用两个指针来记录。因为在计算雨水量的时候,我们只关心左右侧最高柱子中较短的那根,具体做法如下:
定义 low, high 指针分别从数组头尾开始遍历;
定义 maxL, maxR 分别记录当前左右侧最高的柱子;
当 low <= high 时重复:
我们只关心较低的那根柱子,如果 low 柱子低于 high 柱子:
low 柱子高于 maxL,那 low 柱子储存不了雨水,不用管它,更新 maxL 为新高度;
low 柱子低于 maxL,low 柱子能储水,加上储水量;
如果 high 柱子低于 low 柱子:
high 柱子高于 maxR,那 high 柱子储存不了雨水,不用管它,更新 maxR 为新高度;
high 柱子低于 maxR,high 柱子能储水,加上储水量;
复杂度分析
时间复杂度:$O(N)$,N 为数组长度。
空间复杂度:$O(1)$。
代码
JavaScript Code
Last updated
Was this helpful?