刷到一个笑话:字节跳动员工是不是个个都会接雨水。顺便记录一下这道题吧。

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

1
2
3
4
输入: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 个单位的雨水(蓝色部分表示雨水)。

显然需要算出接满水之后的状态数组,即每一个位置的水面高度,然后减掉原本的柱子高度,对数组求和即可。 如何计算水面高度:

  • 如果当前位置的高度大于左右两侧的高度,那么该位置的水面高度就是当前位置的高度,其实就是没有接水;
  • 如果当前位置的高度小于左右两侧的高度,那么该位置的水面高度就是左右两侧的高度中的最小值。

所以问题归结于计算当前位置左侧的最高高度和右侧的最高高度,两次遍历即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution {
public:
int trap(vector<int>& height) {
int length = height.size();

// 计算左边的最大值
vector<int> leftMax(length);
leftMax[0] = height[0];
for (int i = 1; i < length; ++i) {
leftMax[i] = max(leftMax[i - 1], height[i]);
}

// 计算右边的最大值
vector<int> rightMax(length);
rightMax[length - 1] = height[length - 1];
for (int i = length - 2; i >= 0; --i){
rightMax[i] = max(rightMax[i + 1], height[i]);
}

// 根据左右两边的最大值来确定当前柱子所能容纳的总水量,然后求和
int water_sum = 0;
for (int i = 0; i < length; ++i){
water_sum += min(leftMax[i], rightMax[i]) - height[i];
}

return water_sum;
}
};