给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
刚看到这道题的时候,基本没什么思路。但盯着图看了会,突然想到是否可以以上台阶的思路去解决。
所谓上台阶是指我们从一侧开始遍历,当遇到比自己目前所站柱子更高的柱子的时候,就登上去;当遇到跟自己目前所站柱子一样高的柱子时我们就直接走上去;当遇到比自己目前所站的柱子低的柱子时,为了防止我们摔伤,我们需要填充柱子或者叫雨水。登上最高的柱子后,一侧的遍历结束。转头从另一侧开始执行上台阶的步骤。最终我们填充的柱子或雨水数就是答案。代码如下
class Solution {
public int trap(int[] height) {
if(height.length==0) {
return 0;
}
int step = 0;
int rains = 0;
int maxHeightI = 0;
int maxHeight = height[0];
for(int i=1;i<=height.length-1;i++) {
if(height[i] >= maxHeight) {
maxHeight = height[i];
maxHeightI = i;
}
}
for(int i=0;i<=maxHeightI;i++) {
if(height[i] > step) {
step = height[i];
} else if(height[i] < step){
rains += step - height[i];
}
}
step = 0;
for(int i=height.length-1;i>maxHeightI;i--) {
if(height[i] > step) {
step = height[i];
} else if(height[i] < step){
rains += step - height[i];
}
}
return rains;
}
}
我们用step来表示我们目前所站的高度,初始为0。rains表示最终结果,初始为0。我们首先需要用一次遍历去查找最高的柱子所在的下标。可能有多个最高值,我们取最后一个。
然后我们从左侧开始遍历,如果柱子的高度大于我们目前所站的高度,就把柱子的高度赋值给step,相当于我们爬上了新的柱子;如果柱子高度小于我们目前所站的高度,为了防止我们摔伤,我们要填充柱子高度与我们目前所站高度的差值。填充的值累加到rains。当我们碰到最高值,循环结束。
将step清零,从右侧开始遍历,逻辑是一样的。
最终返回rains就是结果。
看了官网的几种解法,感觉不太好理解。基于上台阶的思路比较容易理解。时间复杂度是O(n),我们需要两遍遍历;空间复杂度方面使用了step和maxHeightI变量,复杂度是O(1)。时间复杂度和空间复杂度也能够接受