给定 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 个单位的雨水(蓝色部分表示雨水)。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
需要从最高的柱子算起,每次从当前需要计算的柱子中找到最高的,再从最高的柱子出发,找到次高的柱子,计算一次容量。下一次计算以次高的柱子为出发点
class Solution {
private int result = 0;
/**
* 取两个边界框 如果中间有高度低于两个边界就可以接
*/
public int trap(int[] height) {
oCal(height, 0, height.length - 1);
return result;
}
private void oCal(int[] heights, int left, int right) {
if (right - left <= 1) {
return;
}
int maxIndex = left;
for (int i = left; i <= right; i++) {
if (heights[i] > heights[maxIndex]) {
maxIndex = i;
}
}
// 左边
int leftMaxIndex = -1;
for (int i = maxIndex - 1; i >= left; i--) {
if (leftMaxIndex == -1) {
leftMaxIndex = i;
continue;
}
if (heights[i] > heights[leftMaxIndex]) {
leftMaxIndex = i;
}
}
if (leftMaxIndex != -1) {
result += calCap(leftMaxIndex, maxIndex, heights);
}
// 右bian
int rightMaxIndex = -1;
for (int i = maxIndex + 1; i <= right; i++) {
if (rightMaxIndex == -1) {
rightMaxIndex = i;
continue;
}
if (heights[i] > heights[rightMaxIndex]) {
rightMaxIndex = i;
}
}
if (rightMaxIndex != -1) {
result += calCap(maxIndex, rightMaxIndex, heights);
}
if (leftMaxIndex != -1) {
oCal(heights, left, leftMaxIndex);
}
if (rightMaxIndex != -1) {
oCal(heights, rightMaxIndex, right);
}
}
private int calCap(int i, int j, int[] h) {
int minVal = Math.min(h[i], h[j]);
int r = 0;
for (int k = i + 1; k < j; k++) {
r += minVal - h[k];
}
return r;
}
}