给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 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
提示:
n == height.length
0 <= n <= 3 * 104
0 <= height[i] <= 105
解题思路:一开始想了一个很笨的方法,就是一个高度一个高度遍历上去,首先遍历height数组找到最高的列,然后从高度1到最高高度,进行遍历,在每个高度,确定最左端和最右端,这就是墙,然后中间的如果发现有空着的,那res就加一,空着的高度小于当前遍历到的高度h,这个思路原本是可行的,就是比较费时,在leetcode上通过了319/320个例子,功败垂成,代码如下:
class Solution {
public int trap(int[] height) {
int res = 0, len = height.length;
if(len<3) return res;
int mx = height[0];
for(int h : height) mx = Math.max(mx, h);
if(mx==1) return res;
for(int i=1; i<=mx; i++){
int left = 0, right = len - 1;
while(left<len && height[left]<i) left++;
while(right>0 && height[right]<i) right--;
for(int k=left+1; k<right; k++){
if(height[k]<i) res++;
}
}
return res;
}
}
后来参考了网上的题解,发现了一个相对简洁的方法,这里贴出来,首先就是用两个指针分别指向头尾端点,然后用其中的较小值作为桶的最低一块木板的高度,也就是中间的值都只能小于或等于这个值,如果发现小于等于这个值的数,就在res中加上二者的差值,并且指针前进(左指针向右,右指针向左);如果发现比这个值大的数,那就需要更新最低木板的高度,此时跳出上一步的while循环,继续从头开始,最后,直到两个指针相遇。
代码 t99 s14 java
class Solution {
public int trap(int[] height) {
int res = 0;
int len = height.length, left = 0, right = len - 1;
while(left<right){
int mn = Math.min(height[left], height[right]);
while(left<right && height[left]<=mn){
res += mn - height[left++];
}
while(left<right && height[right]<=mn){
res += mn - height[right--];
}
}
return res;
}
}
参考资料: