【LeetCode热题100】42. 接雨水(双指针)

一.题目要求

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

二.题目难度

困难

三.输入样例

示例 1:

在这里插入图片描述

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。

示例 2:
输入:height = [4,2,0,3,2,5]
输出:9

提示:
n == height.length
1 1 1 <= n <= 2 ∗ 1 0 4 2 * 10^4 2104
0 0 0 <= height[i] <= 1 0 5 10^5 105

四.解题思路

解法1:没用双指针,能想到的就是按每一列对能存的水做计算,
某列存水量 v a l u e = m i n (该列左边所有列的 m a x ,右边所有列的 m a x ) − 该列高 h e i g h t 某列存水量value=min(该列左边所有列的max,右边所有列的max)-该列高height 某列存水量value=min(该列左边所有列的max,右边所有列的max该列高height,由于从左往右遍历,左边最大值易得,但右侧最大值由于始终需要减少一个未知大小的值(即当前列高度),所以只能想到每次都判断的笨方法。
解法2:双指针。
计算公式和上面一样,对于每一列来说,都有其左右侧的maxLeft和maxRight,故对于左右指针Left和Right,也一样有左指针的LMaxLeft,LMaxRight和右指针的RMaxLeft和RMaxRight,若要求当前指针所指列的存水量value,(以左值针为例),我们可以很容易的求得左指针的LMaxLeft当前右指针的RMaxRight,但左指针的LMaxRight和右指针的RMaxLeft无法求出(因为没遍历到),但事实上,针对当前左指针所指列,我们无需求出LMaxRight,因为这时候会存在两种情况:
(1)LMaxLeft < RMaxRight
这种情况下,由计算公式,显然左指针所指的列有可能存水,我们有了LMaxLeft,还需求出LMaxRight,但此时RMaxRight > LMaxLeft,且根据坐标轴朝向,一定会有 LMaxRight >= RMaxRight,所以我们此时不需要考虑LMaxRight的值,它一定比RMaxRight要小,且又有LMaxLeft < RMaxRight,所以此时该列的可能存水量表达式一定为 v a l u e = L M a x L e f t − c u r r e n t H e i g h t value = LMaxLeft - currentHeight value=LMaxLeftcurrentHeight。而后该列判断完,将Left左移,同时更新LMaxLeft。
(2)LMaxLeft >= RMaxRight
表明右指针所指的列有可能存水,此时思路同上, v a l u e = R M a x R i g h t − c u r r e n t H e i g h t value = RMaxRight - currentHeight value=RMaxRightcurrentHeight

五.代码实现

解法1

class Solution {
public:
    int trap(vector<int>& height) {
        int i,j;
        int _trap=0;
        int maxLeftH=height[0],maxRightH=-1;
        for(i=0;i<height.size()-1;i++)
        {
            if(i==0||i==height.size()-1) continue;
            int currentH=height[i];
            //vector<int> tmp=height;
            for(j=i+1;j<height.size();j++)
            {
                maxRightH=max(maxRightH,height[j]);
            }
            //sort(tmp.begin()+i+1,tmp.end());
            //maxRightH=tmp[size(tmp)-1];

            if(maxLeftH>currentH&&maxRightH>currentH)
            {
                _trap+=min(maxLeftH,maxRightH)-currentH;
            }
            maxLeftH=max(maxLeftH,currentH);
            maxRightH=-1;
        }
        //1 1 2 1 1 
        return _trap;
    }
};

解法2

class Solution {
public:
    int trap(vector<int>& height) {
        int i,j;
        int _trap = 0;
        int maxLeftH = height[0],maxRightH = height[size(height)-1];
        
        for(i = 0, j = height.size()-1; i<j ;)
        {
            if(maxLeftH < maxRightH)
            {
                _trap += min(maxLeftH,maxRightH) - height[i];
                i++;
                maxLeftH = max(maxLeftH,height[i]);
            }
            else
            {
                _trap += min(maxLeftH,maxRightH) - height[j];
                j--;
                maxRightH = max(maxRightH,height[j]);
            }
        }
        return _trap;
    }
};

六.题目总结

解法还涉及到动态规划和栈,后续学到会补上。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值