原题:
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
For example,
Given [0,1,0,2,1,0,1,3,2,1,2,1]
, return 6
.
The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!
图片比较直观,看图就可以,给定数组元素index表示横坐标,值表示纵坐标,求蓝色部分面积。
思考过程:
这种题如果用人脑思维来解决,画图就很方便。所谓直观,可能是人脑擅长处理图片信息,可以不通过数据。人画出图来,直接能看出柱子高低,也可能是一种数据比较。自然界也许可以数字化,谁知道中华传统文化中的阴和阳是不是和现在的计算机有异曲同工之妙呢。这种找出“坑”来存水的数据比较规律,是难找的。每个坑满足两边高于中间,坑的两边要么等高,要么有一边高。所以正着遍历一遍数组,找到右边比左边高的坑,倒着遍历数组找到左边不比右边矮的坑。
解题思路:
先正着遍历数组:以 i 为坑的左边,向后遍历,并且把左边高度减去当前的高度作为水的体积,存储到int型变量amount中,直到后面的比坑的左边高,那它就可以为坑的右边,把amount加到结果里。如果遍历到数组最后一个元素,而且它没有左边高,那就将amount设为0.每次遍历玩都记录遍历次数count,下次在i+count处继续遍历。然后反着来,原理一样,就是要注意两边等高的情况。
结果代码:
public int trap(int[] height) {
int ret = 0;
for (int i = 0;i < height.length - 2;i++){//正着遍历数组,找到右边高的坑
int count = 1,amount = 0;
while (height[i + count] < height[i]){
if (i + count == height.length - 1) {//如果到了数组末尾,说明这个坑不存在了,直接跳出,amount的值无效了,设为0
amount = 0;
break;
}
else amount += (height[i] - height[i + count]);//计算雨水数量
count++;
}
ret += amount;i += (count - 1);//遍历过的不再遍历
}
for (int i = height.length - 1;i > 1;i--){//倒着遍历
int count = 1,amount = 0;
while (height[i - count] <= height[i]){
if (i - count == 0) {
amount = 0;
break;
}
else amount += (height[i] - height[i - count]);
count++;
}
ret += amount;i -= (count - 1);
}
return ret;
}