leetcode_42.接雨水

给定 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

解析:本题有多种解法,这里仅提供最后一种的代码,其余方法仅提供思路
一、暴力法,对于每一个格子,它能承载的水量是由它左右两侧的两个最高点中的较低点决定,因此对每一个格子进行两侧扩张找到最高点便可得出结果。时间复杂度为O(n2)。

二、方法一中,每一个格子都要进行搜索,对于两个相邻的格子,它左右两侧基本没有什么变化,这样会浪费大量的资源。因此定义两个数组,分别存放此点左右两侧最高点。最后再遍历一次,根据之前的两个数组获取结果
步骤:
找到数组中从下标 i 到最左端最高的条形块高度left_max[i]
找到数组中从下标 i 到最右端最高的条形块高度right_max[i]
每个点的水量即为min⁡(max_left[i],max_right[i])-height[i]
时间复杂度减少到了O(n),共遍历三遍。但是占用了O(n)的空间

三、双指针法,无论是哪一种方法,都需要两个值,即左侧最高点与右侧最高点,与其不断重复的寻找,不如在运行过程中更新。
定义两个指针left,right,分别指向数组的开头与结尾,并定义两个变量lmax与rmax分别记录左侧最大值与右侧最大值。
每次指针移动后,将指针指向的值与已知最大值进行比较,对lmax与rmax进行更新。
之后比较两个最大值,根据木桶效应,集水量由其中较小的一个决定。
若lmax大于rmax,此时右指针以右的点中的最大值小于左指针以左点中的最小值,且因为左右指针中间的数字尚不知道。可以得到右指针以右点的最大值小于右指针以左点的最大值,即右指针所指点的积水量由右侧最大值rmax决定。于是我们计算右指针所指点的积水量,并累加到总积水量中。之后将右指针左移
若rmax大于lmax,与上文相反,可以得出左指针所指点的积水量,同理将左指针右移。
最后当左右指针相遇,我们就遍历了每一个点,也因此获得了整个数组的总积水量。

class Solution {
public:
    int trap(vector<int>& height) {
        //左右指针
        int res = 0, left = 0, right = height.size() - 1;
        //左右两侧最大值
        int lmax = 0, rmax = 0;
        while(left<right){
        	//更新最大值
            lmax = max(lmax,height[left]);
            rmax = max(rmax,height[right]);
            //计算积水量
            if(lmax < rmax) { 
                res += lmax - height[left];
                ++left;
            }
            else { 
                res += rmax - height[right];
                --right;
            }
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值