42. 接雨水【力扣】

这篇博客探讨了一道算法题目,涉及计算一组不均匀柱子在下雨后能接住的雨水量。博主分享了两种解决方案:一是利用栈,当遇到下降柱子时入栈,遇到上升柱子时计算接雨水量;二是通过动态规划分别计算每个点的左边和右边最高点,然后计算雨水量。博客强调了算法理解和练习的重要性,并提供了详细的代码实现。
摘要由CSDN通过智能技术生成

题意理解

给定高低不均匀的一组柱子高度,计算下雨后可以接住的雨水数量。

问题分析

用栈。

思路还是放在入栈和出栈上。

如果是下降,那么直接入栈。

如果是上升,开始处理接住的雨水数量。每上升一次,计算接住的数量,一层一层往上累加

 

用动规。

思路是两个动规预处理

分别计算每个点的左边最高处和右边最高处,min(左边最高处,右边最高处)- 这个点的高度,大于0就是雨水集赞的高度。一列一列往右扩展。

左边最高处可以动规计算出来,右边最高处可以动规计算出来。

其他

https://leetcode-cn.com/problems/trapping-rain-water/submissions/

此题甚难,明白了练好算法是要花时间的,如果喜欢,花再多的时间也愿意啊。

20210430:  一年了,还是刷算法来的安心。

链接

class Solution {
public:
    int trap(vector<int>& height) {
        stack<int> my_stack;  //特殊栈
        int len = height.size();
        int rains = 0;

        for (int i = 0; i < len; i ++) {
            while(!my_stack.empty() && height[i] > height[my_stack.top()]) {
                int top = my_stack.top(); //获取底盘
                my_stack.pop();
                if (my_stack.empty()) {  //取不到第二个栈元素,说明是靠边了,去掉
                    break;
                }
                int dis = i - my_stack.top() - 1;  // i 是右边沿 my_stack.top() 是左边沿
                int depth = min(height[i], height[my_stack.top()]) - height[top];
                rains += dis * depth;
            }
            my_stack.push(i);
        }
        return rains;
    }
};

 

class Solution {
public:
    int trap(vector<int>& height) {
        int len = height.size();
        if (len <= 1) return 0;
        vector<int> leftMax(len); //左高度
        leftMax[0] = 0;
        for (int i = 1; i < len; i ++) {
           leftMax[i] = leftMax[i-1] > height[i-1] ? leftMax[i-1] : height[i-1];
           //cout << leftMax[i] << '\t';
        }
        //cout << endl;
        vector<int> rightMax(len);
        rightMax[len-1] = 0;
        for (int i = len-2; i >= 0; i --) {
            rightMax[i] = rightMax[i+1] > height[i+1] ? rightMax[i+1] : height[i+1];
            //cout << rightMax[i] << '\t';
        }
        //cout << endl;
        int res = 0;
        for (int i = 1; i < height.size()-1; i++) {
            if (leftMax[i] == 0) continue;
            if (rightMax[i] == 0) continue;
                int lowHeight = min(leftMax[i], rightMax[i]);
                res += (lowHeight > height[i]) ? (lowHeight - height[i]) : 0;
                //cout << leftMax[i] << '\t' << rightMax[i] << '\t' << height[i] << '\t' << res << '\n';
            
        }
        return res;
    }
};

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值