leetcode 42. 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.

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. Thanks Marcos for contributing this image!

Example:
在这里插入图片描述

Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6

解法一:
收集雨水:只需要记录当前位置左侧最大值,右侧最大值,如果当前位置高度小于左侧最大值和右侧最大值的最小值,则当前位置的积水量为 这个最小值 减去 当前位置高度,否则当前位置不积水。
用vector 容器记录当前位置的最大值和最小值。
所以空间复杂度为o(2n),时间复杂度为o(3n)。
代码如下:

int trap(vector<int>& height) {
        int res=0,mx=INT_MIN,n=height.size();
        vector <int> maxleft(n,INT_MIN);// 一个大小为n容器,初始化为最小值,记录左侧最大值
        vector <int> maxright(n,INT_MIN);// 一个大小为n容器,初始化为最小值,记录右侧最大值
        for(int i=0;i<n;++i){
            maxleft[i]=mx;
            mx=max(mx,height[i]);
        }
        mx=INT_MIN;
        for(int i=n-1;i>=0;--i){
            maxright[i]=mx;
            mx=max(mx,height[i]);
        }
        for(int i=1;i<n-1;++i){// 记录积水量
            int minmax=min(maxleft[i],maxright[i]);
            if(height[i]<minmax)res+=minmax-height[i];
        }
        return res; 
    }

解法二:
对解法一进行优化 空间复杂度o(n),时间复杂度o(2n),用一个容器。

    int trap(vector<int>& height) {
        int res=0,mx=INT_MIN,n=height.size();
        vector <int> maxdp(n,INT_MIN);// 一个大小为n容器,初始化为最小值,记录当前位置的左侧最大值和右侧最大值的较小者

        for(int i=0;i<n;++i){//现存左侧最大值
            maxdp[i]=mx;
            mx=max(mx,height[i]);
        }
        mx=INT_MIN;//此时记录右侧最大值
        for(int i=n-1;i>=0;--i){
            maxdp[i]=min(mx,maxdp[i]);//记录当前位置的左侧最大值和右侧最大值的较小者
            mx=max(mx,height[i]);
            if(height[i]<maxdp[i])res+=maxdp[i]-height[i];//记录最大积水值  
        }
        return res; 
    }

解法三:
时间复杂度为O(1),空间复杂度为O(n)

    int trap(vector<int>& height) {
        int res=0,l=0,r=height.size()-1,lever=INT_MIN;
        while(l<r){
            int lower=height[height[l]<height[r]?l++:r--];//记录左边和右边较小的值,这样除了递增和边界有积水,这样记录最小值,这样不会取到最大值,只会取到较小值
            lever=max(lever,lower);//记录最小值中的最大值,相当于两侧最大值的较小值。
            res+=lever-lower; //记录积水量  
        }
        return res; 
    }

更好理解了

    int trap(vector<int>& height) {
        int res=0,l=0,r=height.size()-1,leftmax=INT_MIN,rightmax=INT_MIN;
        while(l<r){//双指针
            if(height[l]<height[r]){//左边值小于右边值,此刻不需要知道右面最大值,只需要知道左边最大值即可
                if(height[l]>=leftmax)leftmax=height[l];
                else res+=leftmax-height[l];
                ++l;//递增
            }
            else{//左边值大于右边值,不需要知道左面最大值,只需要知道右面最大值
                if(height[r]>=rightmax)rightmax=height[r];
                else res+=rightmax-height[r];
                --r;//递减
            }
        }
        return res; 

还可以用堆栈方法解决。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值