当前位置:网站首页>使用单调栈解决接雨水问题——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;
}
};
边栏推荐
- 【我想要老婆】
- 此时已莺飞草长,愿世间美好与你环环相扣
- 1161. Maximum Level Sum of a Binary Tree
- 【论文笔记】—低照度图像增强—Supervised—RetinexNet—2018-BMVC
- [想要访问若依后台]若依框架报错401请求访问:error认证失败,无法访问系统资源
- New Questions in Module B of Secondary Vocational Network Security Competition
- 解决循环依赖import cycle not allowed的最佳解决办法
- Detailed ResNet: What problem is ResNet solving?
- 为什么手动启动GBase 8c数据库中GTM节点,起不来。显示“Run cmd failed:scp: /tmp/gtm_gtm1.server: Permission denied”
- 高等代数_证明_对称矩阵属于不同特征值的特征向量正交
猜你喜欢
随机推荐
Distributed Computing MapReduce | Spark Experiment
千古第一文人苏轼的众CP
金仓数据库KingbaseES客户端编程接口指南-JDBC(10. JDBC 读写分离最佳实践)
全国职业院校技能大赛网络安全竞赛之应急响应
【论文笔记】—低照度图像增强—Supervised—RetinexNet—2018-BMVC
解决报错: YarnScheduler: Initial job has not accepted any resources
RHCSA第五天
中职网络安全竞赛C模块MS17-010批量扫描
高等代数_证明_对称矩阵一定能够相似对角化
DropBlock: Regularization method and reproduction code for convolutional layers
无人驾驶运用了什么技术,无人驾驶技术是
Distributed Computing Experiment 1 Load Balancing
redis stream 实现消息队列
unity2D横版游戏教程7-敌人AI死亡效果
一天学会JDBC06:PrepaerdStatemtnt
小程序如何使用订阅消息(PHP代码+小程序js代码)
在线问题反馈模块实战(十八):实现excel台账文件记录批量导入功能
IntelliJ新建一个类或者包的快捷键是什么?
Praat:语音标注工具【保存为TextGrid文件】
【JS 逆向百例】某网站加速乐 Cookie 混淆逆向详解









