42. 接雨水
好多天没有更新算法题了,前段时间在为一个软件设计大赛准备,一直在开发软件,所以没写算法题,不过这几天一直在写,也为6月10号的蓝桥杯做准备。多余的不说了,接下来请看题
给定 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 个单位的雨水(蓝色部分表示雨水)。
示例 2:
输入:height = [4,2,0,3,2,5]
输出:9
这道题是力扣hot100题双指针的一道困难题,我刚开始做也有思路,但是没有写出来好的代码,然后看了别人的题解做出来了,当然我也总结一下我的做法。
解题思路
- 先给大家分析一下,怎么样我们才能接到雨水呢,当然是当所在位置的高度小于左边跟右边的高度时,才能接到Math.min(左边高度,右边高度) - 当前位置高度的雨水,比如说下图,能接到的水就是 1。
-
那么关于本题该怎么解决呢?其实也就是找每个位置能接多少水,然后把所有的加起来,不就是总的接水量吗。
-
那么我们要知道每个位置
左边的高度
,右边的高度
。那么这所说的不仅仅是该位置相邻的左右两个位置高度,而是所有左边最高的高度,所有右边位置最高的高度。比如下图
-
因此,我们需要遍历题中数组,需要一个指针从左遍历,并寻找leftMax,另一个指针从右遍历,寻找rightMax.
具体java代码如下:
class Solution {
public int trap(int[] height) {
int left = 0;
int right = height.length - 1;
int leftMax = 0;
int rightMax = 0;
int sum = 0;
while(left < right){
leftMax = Math.max(leftMax, height[left]);
rightMax = Math.max(rightMax, height[right]);
if(height[left] < height[right]){
//height[left] < height[right] 的时候 leftmax < rightmax
sum += (leftMax - height[left]);
left++;
}else{
sum += (rightMax - height[right]);
right--;
}
}
return sum;
}
}
或许有人疑问为什么height[left] < height[right]的时候leftmax < rightmax。我给大家举个反例就能明白了。看下图
大家迷惑可能就是这个图的样子,height[left] = 2 < height[righe] = 4 但是leftMax = 5 > rightMax = 4。这个图确实是这个样子的。
但是我们去看我们的程序,假如说从左第一个开始
- leftMax = height[left] = 5。 rightMax = height[right] = 4
- 这时我们该进行else部分,是right–。
- right向左移动一位,那么left不动,所以不会出现我们的上图中的情况的。
大家可以按照代码推一推,推导一遍自然就明白了。