1

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.
rainwatertrap.png
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.

双指针法

复杂度

时间 O(N) 空间 O(1)

思路

我们使用两个指针,一个从左向右遍历,一个从右向左遍历。从左向右遍历时,记录下上次左边的峰值,如果右边一直没有比这个峰值高的,就已经加上这些差值。从右向左遍历时,记录下上次右边的峰值,如果左边一直没有比这个峰值高的,就加上这些差值。难点在于,当两个指针遍历到相邻的峰时,我们要选取较小的那个峰值来计算差值。所以,我们在遍历左指针或者右指针之前,要先判断左右两个峰值的大小。

注意

移动左指针或者右指针时,要先判断left < right

代码

public class Solution {
    public int trap(int[] A) {
        if(A.length < 3) return 0;
        int left = 0;
        int right = A.length - 1;
        int sum = 0;
        // 找到左边的第一个峰值
        while(left < right && A[left] <= A[left+1]) left++;
        // 找到右边的第一个峰值
        while(left < right && A[right] <= A[right-1]) right--;
        while(left < right){
            int leftVal = A[left];
            int rightVal = A[right];
            // 如果左边峰值较小,先计算左边
            if(leftVal < rightVal){
                while(left < right && leftVal >= A[++left]){
                    sum += leftVal - A[left];
                }
            // 如果右边峰值较小,先计算右边
            } else {
                while(left < right && rightVal >= A[--right]){
                    sum += rightVal - A[right];
                }
            }
        }
        return sum;
    }
}

ethannnli
858 声望360 粉丝