LeetCode42-接雨水
42. 接雨水:
给定 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 * 10^4
- 0 <= height[i] <= 10^5
可以参考官方题解,写得挺详细的
官方题解传送门
解题思路1:
预处理左右最值,第i出的最大存水量就是和左右最值的最小值有关
class Solution {
public:
int trap(vector<int>& height) {
int len=height.size();
vector<int>maxleft(len);
vector<int>maxright(len);
maxleft[0]=height[0];
for(int i=1;i<len;++i)
maxleft[i]=max(maxleft[i-1],height[i]);
maxright[len-1]=height[len-1];
for(int i=len-2;i>=0;--i)
maxright[i]=max(maxright[i+1],height[i]);
int ans=0;
for(int i=0;i<len;++i)
ans+=min(maxleft[i],maxright[i])-height[i];
return ans;
}
};
解题思路2:
双指针,考虑一直移动小的一边,计算当前这个格子可以存水量即可
class Solution {
public:
int trap(vector<int>& height) {
int ans=0;
int len=height.size();
int l=0,r=len-1;
int leftmax=0,rightmax=0;
while(l<=r) {
leftmax=max(height[l],leftmax);
rightmax=max(height[r],rightmax);
if(height[l]>=height[r]) {
ans+=rightmax-height[r];
--r;
}
else {
ans+=leftmax-height[l];
++l;
}
//cout<<"ans="<<ans<<endl;
}
return ans;
}
};
解题思路3:
维护一个下标单调不增栈,当遇到比栈顶元素大的数值时候,我们就可以计算这个点的积水量,因为左右两边都比栈顶元素大,可以形成挡板,形成积水
class Solution {
public:
int trap(vector<int>& height) {
int len=height.size();
int ans=0;
stack<int>s;
for(int i=0;i<len;++i) {
while(!s.empty() && height[i]>height[s.top()]) {
int now=s.top();
s.pop();
if(s.empty())
break;
int curLength=i-s.top()-1;
int curHeight=min(height[i],height[s.top()])-height[now];
ans+=curLength*curHeight;
}
s.push(i);
}
return ans;
}
};