Leetcode--接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。

示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

思路 

可以假设有柱子的地方都可以盛满水,即柱子高度+雨水高度= 最高柱子的高度,这样可以盛的总雨水为:柱子的占地(size)× 最高柱子的长度;

这样子的话我们就只要计算两端可能会漏掉的雨水就可以了;

首先先找到最左端和最右端的最高柱子的位置;

然后从两端计算漏掉的雨水;

在最高柱子之间的雨水不会漏掉所以可以不用计算;

最后根据:盛的总雨水= size*maxValue- 会漏掉的雨水- 柱子的面积  计算出结果

class Solution {
public:
    int trap(vector<int>& height) {
        // 删掉两边的0
        int size= height.size();
        int l= 0;
        while(l< size&&!height[l]) l++;
        int r= size- 1;
        while(r>= 0&&!height[r]) r--;
        // 去除0后数组的长度小于2时,返回0
        if(r- l< 2) return 0;

        height= vector<int>(height.begin()+ l, height.end()- (size- r)+ 1);
        size= height.size();

        // 找到最大值的最左和最右的位置
        int maxValue= 0x80000000;
        int maxLeft= 0, maxRight= 0;
        int sum= 0;
        for(int i= 0; i< size; i++){
            if(height[i]> maxValue){
                maxValue= height[i];
                maxLeft= maxRight;
                maxRight= i;              
            }
            sum+= height[i];
        }
        if(height[maxLeft]!= height[maxRight])  maxLeft= maxRight;

        // 从左边开始计算会漏掉的雨水
        int maxTemp= 0;
        int i= -1;
        int subSum= 0;
        while(++i< maxLeft){
            maxTemp= maxTemp> height[i]? maxTemp: height[i];
            subSum+= (maxValue- maxTemp);
        }

        // 从右边开始计算会漏掉的雨水
        maxTemp= 0;
        i= size;
        while(--i> maxRight){
            maxTemp= maxTemp> height[i]? maxTemp: height[i];
            subSum+= (maxValue- maxTemp);
        }

        // 最后的雨水= size*maxValue- 会漏掉的雨水- 柱子的面积
        return size* maxValue- subSum- sum;
    }
}; 

参考Leetcode题解中的官方题解中的双指针法,码了一遍

双指针法在计算其中一端的时候确保了另一端有比当前柱子高的

class Solution {
public:
    int trap(vector<int>& height) {
        int maxLeft= 0, maxRight= 0;
        int left= 0, right= height.size()- 1;
        int result= 0;
        while(left<= right){
            if(height[left]< height[right]){
                height[left]> maxLeft? (maxLeft= height[left]): (result+=  (maxLeft- height[left]));
                ++left;
            }
            else{
                height[right]> maxRight? (maxRight= height[right]): (result+= (maxRight- height[right]));
                --right;
            }
        }
        return result;
    }
}; 
发布了208 篇原创文章 · 获赞 28 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/weixin_41879093/article/details/105309503