给定 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
思路:不去考虑计算每一格的雨水量,直接计算整体雨水量
雨水面积 = 总面积(雨水 + 黑块)- 黑块
总面积 = 每层面积的和
解题方法
双指针
- 计算黑色部分面积:显然为数组求和
- 计算总(黑色+ 雨水)面积:一层一层求出每一层的面积后求和
- 雨水面积 = 总面积 - 黑色面积
那么怎么计算每一层的面积呢,我们可以使用双指针(详细见代码注释)
首先定义一个前一层高度preHeight,初始化为0
步骤1、左指针右移、右指针左移并跳过所有高度小于等于前一层高度的点
步骤2、当前层高度(左右指针较小的值 - 前一层高度preHeight)* 该层宽度,并加入总面积中,同时更新前一层高度preHeight
class Solution {
public int trap(int[] height) {
if(height.length < 3) {
return 0;
}
int l = 0;
int r = height.length -1;
int preHeight = 0;
// 总黑块面积为数组所有数求和
int black = (int)Arrays.stream(height).sum();
//定义雨水 + 黑色面积
int total = 0;
while (l < r) {
while(l<r && height[l] <= preHeight){
l++;
}
while (l<r && height[r] <= preHeight) {
r--;
}
// 计算面积
total += (Math.min(height[l], height[r]) - preHeight) * (r - l + 1);
preHeight = Math.min(height[l], height[r]);
}
return total - black;
}
}
执行用时分布
3ms
击败27.49%使用 Java 的用户
消耗内存分布
45.56MB
击败5.07%使用 Java 的用户