给定 n
个非负整数表示每个宽度为 1
的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。(可以看到需要左右两边都有柱子才能接到雨水,所以第一个和最后一个元素可以不用管。)
提示:
n == height.length
1 <= n <= 2 * 10^4
0 <= height[i] <= 10^5
解法:求每一列可以容纳的雨水量,通过找到这一列的左右两个最高柱子,然后取最小的即可。然后将每一列的可容纳水量累加即可。
思路:windliang
class Solution {
public int trap(int[] height) {
int sum = 0;
for(int i = 1; i < height.length - 1; i++){
int max_left = 0;
for(int j = i - 1; j >= 0; j--){
if(height[j] > max_left) {
max_left = height[j];
}
}
int max_right = 0;
for(int j = i + 1; j < height.length; j++){
if(height[j] > max_right){
max_right = height[j];
}
}
int min = Math.min(max_left, max_right);
int tmp = min > height[i] ? min - height[i] : 0; // 该列可容纳水量
sum += tmp;
}
return sum;
}
}
优化:使用max_left[],max_right[]两个数组,分别去存该列的左右两边最高的柱子,我们只需要通过比较前面列的最大高度柱子和当前柱子高度比对一次max(max_left[ i - 1], height[i - 1])和max(max_right[i + 1], height[i + 1]),也就是只需要遍历一次。
class Solution {
public int trap(int[] height) {
int sum = 0;
int[] max_left = new int[height.length]; // max_left[i]代表i左边最高的墙
int[] max_right = new int[height.length]; // max_right[i]代表i右边最高的墙
for (int i = 1; i < height.length - 1; i++) {
max_left[i] = Math.max(max_left[i - 1], height[i - 1]);
}
for (int i = height.length - 2; i > 0; i--) {
max_right[i] = Math.max(max_right[i + 1], height[i + 1]);
}
for (int i = 1; i < height.length - 1; i++) {
int min = Math.min(max_left[i], max_right[i]);
int tmp = min > height[i] ? min - height[i] : 0;
sum += tmp;
}
return sum;
}
}