42. Trapping Rain Water

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.
在这里插入图片描述

这道收集雨水的题目,非常的有意思。
使用单调栈作为数据结构进行处理。
单调栈的一大优势就是线性的时间复杂度,所有的元素只会进栈一次,而且一旦出栈后就不会再进来了。
单调递增栈可以找到左起第一个比当前数字小的元素。
单调递减栈可以找到左起第一个比当前数字大的元素。

  • 分析:
    给了边界的高度(黑色部分),让求能装的水量(蓝色部分)。 为啥能用单调栈来做呢?我们先来考虑一下,什么情况下可以装下水呢,是不是必须两边高,中间低呢?我们对低洼的地方感兴趣,就可以使用一个单调递减栈,将递减的边界存进去,一旦发现当前的数字大于栈顶元素了,那么就有可能会有能装水的地方产生。此时我们当前的数字是右边界,我们从栈中至少需要有两个数字,才能形成一个坑槽,先取出的那个最小的数字,就是坑槽的最低点,再次取出的数字就是左边界,我们比较左右边界,取其中较小的值为装水的边界,然后此高度减去水槽最低点的高度,乘以左右边界间的距离就是装水量了。由于需要知道左右边界的位置,所以我们虽然维护的是递减栈,但是栈中数字并不是存递减的高度,而是递减的高度的坐标
class Solution {
public:
    int trap(vector<int>& height) {
        int n = height.size();
        if(n<=2) return 0;
        int res = 0;
        stack<int> s;
        
        for(int i=0;i<n;++i) {
            if(s.empty()||height[i]<=height[s.top()])
                s.push(i);//递减则入递减栈
            else {
            	//出现非递减的元素,则为右边界,将栈当中小于此边界的元素弹出计算可储水的量。
                while(!s.empty()&&height[i]>height[s.top()]) {
                //这里一定是while循环 如果左边有多个元素小于当前压栈值 持续出栈计算面积 
                    int t = s.top();
                    s.pop();
                    //特殊情况 就是说没有左边界,此时需要判断栈是否为空如果为空直接跳出
                    if(!s.empty()) {
                    //根据左右边界计算面积
                        int l = s.top();
                        int h = min(height[l],height[i]) - height[t];
                        int w = i - l - 1;
                        res += h*w;
                    }
                }
                s.push(i);
            }
        }
        return res;
    }
};

每一个元素只有一次入栈和出栈,所以整体的时间复杂度为o(n)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值