当前位置:网站首页>使用单调栈解决接雨水问题——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;
}
};
边栏推荐
- GBase 8c数据库集群中,怎么替换节点呢?比如设置A节点为gtm,换到B节点上。
- 在安装GBase 8c数据库的时候,报错显示“Host ips belong to different cluster”。这是为什么呢?有什么解决办法?
- 一天学会JDBC03:Statement的用法
- MySQL 8.0.29 详细安装(windows zip版)
- 在线问题反馈模块实战(十八):实现excel台账文件记录批量导入功能
- 2022的七夕,奉上7个精美的表白代码,同时教大家改源码快速自用
- 金仓数据库的单节点如何转集群?
- 七夕情人节:中英文祝福短信送给你
- likeshop外卖点餐系统【100%开源无加密】
- data:image/jpg; base64 format data is converted to image
猜你喜欢
随机推荐
金仓数据库KingbaseES客户端编程接口指南-JDBC(10. JDBC 读写分离最佳实践)
国内外知名源码商城系统盘点
【我想要老婆】
实现加载驱动、得到数据库对象、关闭资源的代码复用,将代码提取到相应的工具包里边。优化程序
Typora_Markdown_图片标题(题注)
最近的一些杂感-20220731
简析强制缓存和协商缓存
小猫爪:AWR294x学习笔记02-AWR294x之DPM&IPC
8.2学习记录
babylon 里面加gltf 模型
全国职业院校技能大赛网络安全竞赛之应急响应
LLVM编译技术应用分析
GBase 8c数据库集群中,怎么替换节点呢?比如设置A节点为gtm,换到B节点上。
高等代数_证明_幂等矩阵一定能够相似对角化
金仓数据库KingbaseES客户端编程接口指南-JDBC(7. JDBC事务处理)
沃尔玛、阿里国际该如何做测评自养号?
千古第一文人苏轼的众CP
【JS 逆向百例】某网站加速乐 Cookie 混淆逆向详解
Distributed Computing Experiment 4 Random Signal Analysis System
Use of MotionLayout