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次。如果谁能说明白希望不吝赐教,万分感谢。