给定 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
1 <= n <= 2 * 104
0 <= height[i] <= 105
解
- 每个位置能承接的雨水取决于左右两边最低的高度-当前的高度.
- 遍历每个位置, 计算左右两边最低的高度. 若大于当前高度则-当前的高度.累计起来
class Solution {
public int trap(int[] height) {
int sum = 0;
for(int i=1; i<height.length-1; i++){
sum = sum + trap(height, i);
}
return sum;
}
public int trap(int[] height, int i) {
int left = 0;
int right = 0;
for (int l = i; l >= 0; l--) {
if (height[l] > left) {
left = height[l];
}
}
for (int r = i; r < height.length; r++) {
if (height[r] > right) {
right = height[r];
}
}
if(left<=height[i] || right<=height[i]){
return 0;
}
return Math.min(left, right) - height[i];
}
}
- 这里影响时间复杂度的地方在于每次都需要重新遍历左右最大高度.
- 如果我们先遍历一次, 把每个位置的左右最大高度都计算保存起来. 那么循环两次就可以完成计算了
class Solution {
public int trap(int[] height) {
int[] leftM = new int[height.length];
int[] rightM = new int[height.length];
int lT = 0;
int rT = 0;
leftM[0] = 0;
rightM[height.length - 1] = 0;
for (int i = 0, j = height.length - 1; i < height.length; i++, j--) {
if (height[i] > lT) {
lT = height[i];
}
leftM[i] = lT;
if (height[j] > rT) {
rT = height[j];
}
rightM[j] = rT;
}
int sum = 0;
for (int i = 1; i < height.length - 1; i++) {
sum = sum + ((Math.min(leftM[i], rightM[i]) - height[i]) > 0 ? (Math.min(leftM[i], rightM[i]) - height[i])
: 0);
}
return sum;
}
}