给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
思路
首先找到序列中的最大值,再使用两个指针i 和 j 分别从序列两端向最大值扫描,并使用两个临时变量来存储 i 和j在扫描中的最大值,这样,当扫描中的元素小于临时最大值时,则表示该元素和临时最大值之间可以盛水,用变量存一下。这样最后返回该变量即可。
代码
public class Trapping_Rain_Water {
/**
* @return int
* @author chy
* @creed: Talk is cheap,show me the code
* @date 11/4/2019 10:13 PM
* @desc:
*/
public int trap(int[] height) {
int MaxI = 0, MaxJ = 0, sum = 0, maxIndex = 0;// MaxI,MaxJ用来存储i 和 j 扫描时的最大值,sum用来计数能盛水的数量,maxIndex用来标记序列中的最大值
for (int k = 0; k < height.length; k++)//首先找出最大值
if (height[k] > height[maxIndex])
maxIndex = k;
int i = 0, j = height.length - 1;
//开始循环扫描,i从左向右,j从右向左
while ( i < maxIndex || j > maxIndex) {
if (height[i] > MaxI)//更新最大值
MaxI = height[i];
else
sum += MaxI - height[i];//当当前的元素比扫描的最大值小时,则说明它们之间的差值就是盛水的数量,因为右边有序列最大值
if (height[j] > MaxJ)
MaxJ = height[j];
else
sum += MaxJ - height[j];
if(i < maxIndex)
i++;
if(j > maxIndex)
j--;
}
return sum;
}
public static void main(String argc[]) {
System.out.print(new Trapping_Rain_Water().trap(new int[]{0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}));
}
}