首页 > 代码库 > 【LeetCode】Trapping Rain Water解题报告

【LeetCode】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.

【解析】

题意:求数组组成的凹槽能盛水的容积。

思路:从两端向中间靠拢,求以两端为边的容器能盛水的容积,然后所有值都减去短边的值,找到新的两边,不断迭代下去直到中间。

public class Solution {
    public int trap(int[] A) {
        if (A.length < 3) return 0;
        
        int ans = 0;
        int l = 0, r = A.length - 1;
        while (l < r) {
            // find the left edge and right edge
            while (l < r && A[l] == 0) l++;
            while (l < r && A[r] == 0) r--;
            
            //get the shoter edge, which decides the volum
            int min = Math.min(A[l], A[r]); 
            
            // compute the volum from A[l] to A[r]
            int tmp = 0;
            for (int i = l; i <= r; i++) {
                if (A[i] >= min) {
                    A[i] -= min;
                } else {
                    tmp += min - A[i];
                    A[i] = 0;
                }
            }
            
            // add to the result
            ans += tmp;
        }
        return ans;
    }
}


【升级版】【O(n)】

首先找到有效的两边,如 [0, 1, 2, 3, 0, 3, 2, 1, 0],递增的左边和递减的右边是不能盛水的。

然后选择较短的边,如果是左边就开始右移,直到找到一个比左边高的边,更新左边;如果是右边较短,就左移,直到找到一个更高的边,更新右边。

public class Solution {
    public int trap(int[] A) {
        if (A.length < 3) return 0;
        
        int ans = 0;
        int l = 0, r = A.length - 1;
        
        // find the left and right edge which can hold water
        while (l < r && A[l] <= A[l + 1]) l++;
        while (l < r && A[r] <= A[r - 1]) r--;
        
        while (l < r) {
            int left = A[l];
            int right = A[r];
            if (left <= right) {
                // add volum until an edge larger than the left edge
                while (l < r && left >= A[++l]) {
                    ans += left - A[l];
                }
            } else {
                // add volum until an edge larger than the right volum
                while (l < r && A[--r] <= right) {
                    ans += right - A[r];
                }
            }
        }
        return ans;
    }
}


【LeetCode】Trapping Rain Water解题报告