42. 接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
解法思路
解法一
先创建两个预数组
一个存当前指针左边最大值 一个存当前指针右边最大值
然后计算每格上面的水分
public static int maxArea(int[] height) {
// 每一个上面都是取 MIN(左边最大,右边最大) - 自己 负数取0
// 创建左最大数组 和 右最大数组
int[] left = new int[height.length];
int[] right = new int[height.length];
int leftMax = 0;
int rightMax = 0;
int sum = 0;
for (int i = 0; i < height.length; i++) {
if (height[i] > leftMax) {
leftMax = height[i];
}
if (height[height.length - i - 1] > rightMax) {
rightMax = height[height.length - i - 1];
}
left[i] = leftMax;
right[height.length - i - 1] = rightMax;
}
// 求总和
for (int i = 0; i < height.length; i++) {
int diff = Math.min(left[i], right[i]) - height[i];
sum = sum + Math.max(diff, 0);
}
return sum;
}
解法二
直接用左右指针的方法
- 因为一个格子可以存的水等于左边最高和右边最高两者的小的那一个(木桶效应, 之后我们称这个值为短板) 减去当前高度 最少为0
- 所以我们通过左右指针的方式 可以获取当前左边最大值和右边最大值
- 在左指针处的格子 左边的最大值是确定的(因为已经遍历过其左边的所有格子了) 如果右边的最大值比他大或者和他相等 短板就找到了 在右指针处同理
- 这样我们就能在左右指针重合时把所有格子上的水都求出来了
public static int trap(int[] height) {
if (height.length <=2){
return 0;
}
int left = 1;
int right = height.length - 2;
int leftMax = height[0];
int rightMax = height[height.length - 1];
int sum = 0;
while (left <= right) {
if (leftMax < rightMax) {
sum += Math.max(leftMax - height[left], 0);
leftMax = Math.max(height[left], leftMax);
left++;
} else {
sum += Math.max(rightMax - height[right], 0);
rightMax = Math.max(height[right], rightMax);
right--;
}
}
return sum;
}