题目
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
题解
能够接到雨水,则肯定是盆状的设计。因此,我们只需要找到2端较高柱子的位置,就可以计算出在这2个区域内能够接到多少的雨水。
由于同时寻找2个较高的柱子比较难以实现,且可能存在多个盆装的地形,因此,我们首先寻找出这些柱子的最高点 heightest ,再进行讨论。
当我们找到最高点 heightest 时,分别 从左往最高点遍历 和 从右往最高点遍历 ,这2种遍历都遵循以下规则:
①定义指针 tmp 指向最左端(最右端);
②从左往右(从右往左)进行遍历,若下一个值大于 tmp ,则将其赋值给 tmp ,否则,计算水域大小 tmp-height[i] ,继续遍历,直至最高点;
③将水域大小累加,即可得到水域的总面积。
当最高点敲定的时候,左边(右边)的柱体若与下一个柱体(靠近最高点方向)有落差,则必然会被水填满。因为靠近最高点方向必有高于该柱体的柱子存在(最高柱)。因此,每次仅需计算落差值,再累加,即可得到最终数值。
public int trap(int[] height) {
int square = 0;
int left = -1;
int right = -1;
int heightest = -1;
int heightest_index = -1;
List<Integer> mid = new ArrayList<Integer>();
if(height.length <= 1) {
return 0;
}
// 寻找最高点
for(int i = 0; i < height.length; i++) {
if(height[i] > heightest) {
heightest = height[i];
heightest_index = i;
}
}
// 计算左侧
int tmp = height[0];
for(int i = 1; i < heightest_index; i++) {
if(height[i] > tmp) {
tmp = height[i];
}else {
square += tmp - height[i];
}
}
// 计算右侧
tmp = height[height.length-1];
for(int i = height.length-2; i > heightest_index; i--) {
if(height[i] > tmp) {
tmp = height[i];
}else {
square += tmp - height[i];
}
}
return square;
}