leetcode 42 接雨水 单调栈+双指针

初始思路:单调栈
这是个不太寻常的单调栈,但也是可以做的。思路是,如果一直递减,就留着。如果递增,看看左边有没有护着的,有就计数,没有就继续往左走。这样能循环的不断加较低的水坑,挺难想的其实。

class Solution:
    def trap(self, height: List[int]) -> int:
        if not height: return 0
        
        stack = []
        ret = 0
        for i, h in enumerate(height):
            while stack and h >= height[stack[-1]]:
                if len(stack) > 1 and height[stack[-1]] <= height[stack[-2]]:
                    ht = min(h, height[stack[-2]]) - height[stack[-1]]
                    wd = i - stack[-2] - 1
                    ret += ht*wd
                stack.pop()
            stack.append(i)

        return ret

解法二:双指针
这个思路真的是太强了。。
首先咱们理一下思路,只考虑随意一个柱子,它能接的雨水量取决于左边所有柱子的最大值和右边所有柱子最大值的最小者。所以这个题用单调栈做比较费劲就是因为不是仅维护一个最小值所在区间,而是要同时考虑两侧。
这个题用双指针做,从两边开始(最靠边的接不到水),分别维护左边最大值和右边最大值。如果有一方较小,那么这一方的接水量已定,因为右边最大值只会更大,不会更小。如果两边最大值相等,任意移动一个即可。如果都移动,需要考虑二者是否重合,没必要,代码如下:

class Solution {
public:
    int trap(vector<int>& height) {
        int ret = 0;
        int n = height.size();
        if(n < 3)return 0;
        int l = 1, r = n-2;
        int lmax = height[0], rmax = height[n-1];
        while(l<=r)
        {
            if(lmax > rmax)
            {
                ret += max(0, rmax-height[r]);
                rmax = max(rmax, height[r--]);
            }
            else
            {
                ret += max(0, lmax-height[l]);
                lmax = max(lmax, height[l++]);
            }
        }

        return ret;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值