当前位置:网站首页>使用单调栈解决接雨水问题——LeetCode 42 接雨水+单调栈说明
使用单调栈解决接雨水问题——LeetCode 42 接雨水+单调栈说明
2022-08-04 07:28:00 【dor.yang】
题目内容
给定 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 <= n <= 2 * 104
0 <= height[i] <= 105
来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
这道题我一开始也是没有什么头绪,正准备看题解,结果看到单调栈标题,瞬间就懂了(有时候还真的是要多练习才能有一些敏锐度,我都没想到这个)。于是回过头来准备自己写这个。恬不知耻一些,这个也算大半个自己写的吧(doge)。
其实单调栈对于这类问题来说几乎就是天作之合了,单调栈最好的用处就是寻找数组中离自己最近的,比自己大或者小的元素的位置,在这道题这里正好可以看一下积攒雨水的柱子的位置。
我们先来看一下单调栈结构解决找元素位置问题,这个其实我们可以用O(n^2)来解决,但是单调栈的存在可以把这个问题优化到O(N)
我们先说数组中没有重复值的情况,这样好理解一些。如果我们要找的是最近的比自己大的数,那么我们就需要确定一点,那就是单调栈是从大到小排列的(栈底到栈顶)。满足条件的时候,我们直接压栈,但是如果发现有不满足的了,就需要出栈了,然后弹出栈顶之后,他左边的比他大的就是栈里他下面那个,右边那个就是进栈未遂的数据。如果没有就是无,这里会一直出栈知道能够进栈为止。这里一个数据进出栈都只有一次,所以时间复杂度是O(N)
回到题目,首先就是用单调栈实现对于每一个位置找左右比自己高的位置的脚标,这里需要注意的是,最好用脚标才入栈,因为脚标的信息和高度是包含关系,脚标信息更多一些。
然后把所有能找到左右比自己高的位置存在map里,这里其实如果留心一些会发现我们的栈中还是有元素没有出来的,这个就不用管了,这个说明我们最右边有一个下坡的形态,是根本存不下水的。
有了这个数据之后就好处理多了,直接遍历,计算两边柱子能提供的高度-本身的高度。不过在计算好了之后,记得要更新height的数据,不然的话因为存在嵌套关系,会导致结果出现问题。
代码
class Solution {
public:
int trap(vector<int>& height) {
stack<int> dandiao;
map<int,pair<int,int>> mp;
for(int i=0;i<height.size();i++){
if(dandiao.size()==0){
dandiao.push(i);
}
else{
if(height[dandiao.top()]>height[i]){
dandiao.push(i);
}
else{
while(height[dandiao.top()]<=height[i]){
int weizhi=dandiao.top();
dandiao.pop();
int ding=dandiao.size()==0?-1:dandiao.top();
if(mp.find(i)==mp.end()){
mp[weizhi]=pair<int,int>(ding,i);
}
else{
mp[weizhi]=pair<int,int>(ding,i);
}
if(dandiao.size()==0){
break;
}
}
dandiao.push(i);
}
}
}
cout<<mp.size()<<endl;
int ans=0;
for(int i=0;i<height.size();i++){
cout<<i<<":"<<mp[i].first<<" "<<mp[i].second<<endl;
if(mp[i].first==-1){
continue;
}
int low=min(height[mp[i].first],height[mp[i].second]);
cout<<low<<endl;
for(int j=mp[i].first+1;j<mp[i].second;j++){
ans+=((low-height[j]>0)?low-height[j]:0);
height[j]=low;
cout<<ans<<endl;
}
}
return ans;
}
};
边栏推荐
- RT-Thread Studio学习(十二)W25Q128(SPI)的读写
- likeshop单商户高级版企业源码发布了新的版本1.8.1
- 此时已莺飞草长,愿世间美好与你环环相扣
- 第一次用postgreSQL,想装主从,用的12.7 tar.gz版本。安装好后没在 share目录下找到样例配置recovery.conf.sample,是安装方式不对,还是路径不对?
- 金仓数据库 KDTS 迁移工具使用指南 (5. SHELL版使用说明)
- 有趣的USB接口和颜色分类
- Distributed Computing MapReduce | Spark Experiment
- 【字符串】最小表示法
- 异常值 识别与处理方法
- likeshop外卖点餐系统开源啦100%开源无加密
猜你喜欢
随机推荐
有趣的USB接口和颜色分类
adb无法桥接夜神模拟器
卷积神经网络CNN
金仓数据库KingbaseES客户端编程接口指南-JDBC(7. JDBC事务处理)
1161. Maximum Level Sum of a Binary Tree
解决循环依赖import cycle not allowed的最佳解决办法
GBase 8c数据库集群中,怎么替换节点呢?比如设置A节点为gtm,换到B节点上。
【并发】概念
两日总结六
打破千篇一律,DIY属于自己独一无二的商城
leetcode 22.7.31(1)两数之和 (2)整数除法
【剑指Offer】二分法例题
两日总结五
Distributed Computing Experiment 4 Random Signal Analysis System
2022年7月总结
使用腾讯云发送短信 ---- 手把手教你搞定所有步骤
分布式计算实验4 随机信号分析系统
高等代数_证明_对称矩阵一定能够相似对角化
10个程序员可以接私活的平台和一些建议,赚麻...
MySQL 8.0.29 详细安装(windows zip版)



![[想要访问若依后台]若依框架报错401请求访问:error认证失败,无法访问系统资源](/img/aa/701fef9d8d7eaf25082e1289799b77.png)


![(19)[系统调用]SSTD hook 阻止关闭](/img/73/e9d591af366db17965d0bf1cf192b7.png)

