42. Trapping Rain Water

来源:互联网 发布:nginx 配置多目录访问 编辑:程序博客网 时间:2024/05/23 23:48

对于每个柱子,找到其左右两边最高的柱子,该柱子能容纳的面积就是 min(leftMostHeight,rightMostHeight) - height。所以,

1. 从左往右扫描一遍,对于每个柱子,求取左边最大值;

2. 从右往左扫描一遍,对于每个柱子,求最大右值;

3. 再扫描一遍,把每个柱子的面积并累加。

class Solution {public:    int trap(vector<int>& height) {        int res = 0, mx = 0, n = height.size();        vector<int> dp(n, 0);        for (int i = 0; i < n; ++i) {            dp[i] = mx;            mx = max(mx, height[i]);        }        mx = 0;        for (int i = n - 1; i >= 0; --i) {            dp[i] = min(dp[i], mx);            mx = max(mx, height[i]);            if (dp[i] > height[i]) res += dp[i] - height[i];        }        return res;    }};
一种只需要遍历一次即可的解法,这个算法需要left和right两个指针分别指向数组的首尾位置,从两边向中间扫描,在当前两指针确定的范围内,先比较两头找出较小值,如果较小值是left指向的值,则从左向右扫描,如果较小值是right指向的值,则从右向左扫描,若遇到的值比当较小值小,则将差值存入结果,如遇到的值大,则重新确定新的窗口范围,以此类推直至left和right指针重合。

class Solution {public:    int trap(vector<int>& height) {        int res = 0, l = 0, r = height.size() - 1;        while (l < r) {            int mn = min(height[l], height[r]);            if (mn == height[l]) {                ++l;                while (l < r && height[l] < mn) {                    res += mn - height[l++];                }            } else {                --r;                while (l < r && height[r] < mn) {                    res += mn - height[r--];                }            }        }        return res;    }};