leetcode#42接雨水(C语言实现)

题目描述:给定 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
算法思路一
对于任意位置i,求出i位置左边数组的最大值,以及i位置右边数组的最大值,显然i位置能装多少水,取决于两个最大值中较小的一个(设这个数为temp),如果temp>height[i],则i位置可以装水temp-height[i]的水
①使用两个数组left和right数组,left[i]表示i位置左边的最大值,显然有left[i]=max{left[i-1],height[i]},同理right[i]用来表示i位置右边的最大值,显然有right[i]={right[i+1],height[i]}
②从i=1一直遍历到i=height-2,每个位置的装水的综合即是返回值
时间复杂度O(n),空间复杂度O(n)
算法实现一

int trap(int* height, int heightSize){
    if(heightSize<=2) return 0;
    int left[heightSize],right[heightSize];
    int i=0,max=-1,res=0;
    left[0]=height[0],right[0]=height[0];
    for(i=1;i<heightSize;i++){
        left[i]=height[i]>left[i-1]?height[i]:left[i-1];
    }
    for(i=heightSize-2;i>=0;i--){
        right[i]=height[i]>right[i+1]?height[i]:right[i+1];
    }
    for(i=1;i<heightSize-1;i++){
        int min=left[i]>right[i]?right[i]:left[i];
        res+=min-height[i];
    }
    return res;
}

算法思路2:双指针法
使用left=0,right=heightSize-1,同时用rightMax和LeftMax来保存扫描到左右指针位置时的对应最大值。使用循环,两个指针遍历数组,当指针相遇时停止遍历。
因为装水多少是由rightMax和leftMax中更小的值决定的。不失一般性的以left举例:如果leftMax更小,那我们就观察left指针,
①如果height[left]比leftMax小,说明left位置必定可以装水
②反之不能装水,同时更新leftMax的值为height[left]
left位置已经观察过了,所以指针移动left++;
具体算法建议直接看代码,代码实现并不复杂。
时间复杂度O(n),空间复杂度O(1)
算法实现二

int trap(int* height, int heightSize){
    if(heightSize<=2) return 0;
    int left=0,right=heightSize-1;
    int leftMax=height[0],rightMax=height[heightSize-1];
    int ans=0;
    while(left<=right){
        if(leftMax<rightMax){
            if(height[left]<leftMax){
                ans+=leftMax-height[left];
            }else{
                leftMax=height[left];
            }
            left++;
        }
        else{
            if(height[right]<rightMax){
                ans+=rightMax-height[right];
            }else{
                rightMax=height[right];
            }
            right--;
        }
    }
    return ans;
}
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值