Trapping Rain Water

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.

这题最初的想法从头到尾的带回溯遍历,每次计算出一个能够积水的坑,如上图中,有3个能积水的坑,分别能够积水1,4,1,所以总和是6.这个做法因为回溯,所以找出所有坑的复杂度是O(n^2),再计算能够积多少水,复杂度就为O(n^3)了,即使找坑时记录下能够积水信息,复杂度也是O(n^2)了。这个方法比较麻烦不好描述,复杂度也高,就忽略它吧。。。

之前看过这种样子的题,总觉着这样的题复杂度都能在O(n)解决,就往这方面想了想,想出一种思路经过数据验证是正确的,但是为什么可行貌似不能解释的很清楚。

具体算法如下:

分两步:

1.从前往后遍历,不回溯:以起点为轴,向后找到第一个高度大于等于它的下标,计算这两者之间能够装水的体积,然后将轴置为当前下标,再重复上述过程,直到遍历完整个数组。

2.从后往前遍历,不回溯:以终点为轴,向前找到第一个高度大于它的下标(这里不能等于,因为等于的话在第一步计算过,再计算的话重复了),计算这两者之间能够装水的体积,然后将轴置为当前下标,再重复上述过程,直到遍历完整个数组。

然后结果就是上述这两部中计算出的所有能够装水的体积的总和。

代码如下:

 1 public int trap(int[] A) {
 2         if (A == null || A.length <= 1) {
 3             return 0;
 4         }
 5         int zou = 0;
 6         int hold = 0;
 7         int count = 0;
 8         for (int i = 1; i < A.length; i++) {
 9             if (A[i] >= A[zou]) {
10                 hold += (i - zou - 1) * A[zou] - count;
11                 count = 0;
12                 zou = i;
13             } else {
14                 count += A[i];
15             }
16         }
17         zou = A.length - 1;
18         count = 0;
19         for (int i = A.length - 2; i >= 0; i--) {
20             if (A[i] > A[zou]) {
21                 hold += (zou - i - 1) * A[zou] - count;
22                 count = 0;
23                 zou = i;
24             } else {
25                 count += A[i];
26             }
27         }
28         return hold;
29     }

通过了leetcode

 

但是为什么这个想法是正确的现在还没有搞清楚,网上搜的答案好多都是一样的,都要遍历3次。如果谁能说明白希望不吝赐教,万分感谢。

posted @ 2014-05-14 18:42  秋风一片叶  阅读(302)  评论(0编辑  收藏  举报