- 题目描述
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
提示:
n == height.length
0 <= n <= 3 * 104
0 <= height[i] <= 105
来源:LeetCode
- 示例
- 示例 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
- 思路分析
个人觉得这道题挺好想的,动态规划就解决了,寻找凹槽即可。
- 定义 L [ i , j ] L[i,j] L[i,j] = 柱子 i i i和柱子 j j j之间可以接多少水,则 L [ i , j ] = L [ i , k ] + L [ j , k ] L[i,j] = L[i,k]+L[j,k] L[i,j]=L[i,k]+L[j,k], i < k < j i<k<j i<k<j, 且柱子 k k k的高度大于 m i n min min(柱子 i i i,柱子 j j j)。
- 遍历 h e i g h t [ i + 1 ] height[i+1] height[i+1]到 h e i g h t [ j − 1 ] height[j-1] height[j−1]。如果没有比柱子 i i i和柱子 j j j都矮的柱子,说明找到了一个凹槽,就再遍历一遍求出这个凹槽可以装多少水;如果有比柱子 i i i和柱子 j j j都高的柱子 k k k,就分成两部分,分别求出求 L [ i , k ] L[i,k] L[i,k]和 L [ k , j ] L[k,j] L[k,j]即可。
- JAVA实现
class Solution {
public int trap(int[] height) {
int i=0,j=height.length;
if(j<2) return 0; //至少有三个柱子才可能构成凹槽
int sum=0;
return water(height, i, j-1, sum);
}
public int water(int[] height, int i, int j, int sum) {
int max=0, id=i, min=Math.min(height[i],height[j]);
//max:柱子i和柱子j之间的柱子的最大高度,不包含柱子i和j
//id:如果存在max,这个柱子的index
//min:柱子i和柱子j这种更矮的柱子的高度
for(int m=i+1;m<j;m++) {
if(height[m]>max) {
max = height[m];
id = m;
}
}
if(max>min) { //存在更高的柱子,没有形成凹槽,因此分割成两部分
sum = water(height, i, id, sum);
sum = water(height, id, j, sum);
}
else { //形成一个凹槽
for(int k = i+1;k<j;k++)
sum += min-height[k];
}
return sum;
}
}