class Solution {
/**
思路:
只考虑当前位置能装下多少水
比如说
8 2 7
i ... cur ... j
对于当前位置 cur 而言, 左边存在 0...cur - 1 这段区间最大值
右边存在 cur + 1 ... n - 1 这段区间最大值
我们只拿当前位置 cur 和这两个最大值相比, 因为当 cur 小于这两个最大值
中较小的那个时, 那么说明就 cur 位置而言, 能装下的雨水的数量就是
min(leftMax, rightMax) - height[cur] 这么多雨水
如果结果为 负, 则说明无法装下雨水, 则为 0
*/
public int trap(int[] height) {
int N = height.length;
if (N < 3) return 0; // 如果只有少于 3 个柱子, 一定没办法装下雨水
// leftMax[i] 表示 0...i 位置这段区间的最大值
int[] leftMax = new int[N];
// rightMax[i] 表示 i...n - 1 位置这段区间的最大值
int[] rightMax = new int[N];
leftMax[0] = height[0];
rightMax[N - 1] = height[N - 1];
for (int i = 1; i < N; i++) {
leftMax[i] = Math.max(leftMax[i - 1], height[i]);
}
for (int i = N - 2; i >= 0; i--) {
rightMax[i] = Math.max(rightMax[i + 1], height[i]);
}
int ans = 0;
for (int i = 1; i < N - 1; i++) {
// 找出 左右两边的最大值 较小 的那个
int bian = Math.min(leftMax[i - 1], rightMax[i + 1]);
// 累加上当前位置能装下的雨水
ans += Math.max(bian - height[i], 0);
}
return ans;
}
}
class Solution {
/**
优化版本
省去两个预处理数组
*/
public int trap(int[] height) {
int N = height.length;
if (N < 3)
return 0;
int rightMax = height[N - 1];
int leftMax = height[0];
int ans = 0;
int L = 1;
int R = N - 2;
while (L <= R) {
if (leftMax <= rightMax) {
ans += Math.max(leftMax - height[L], 0);
leftMax = Math.max(leftMax, height[L++]);
} else {
ans += Math.max(rightMax - height[R], 0);
rightMax = Math.max(rightMax, height[R--]);
}
}
return ans;
}
}