1.题目链接
https://leetcode.cn/problems/trapping-rain-water/
2.方法一:动态规划
动态规划思路:
如果我们暴力的来做这道题的话,我们就需要找到每一个坑洼处两边的最小值和最大值,但如果我们遍历每一个点来找其周围最大值和最小值的话就会很费时间,我们这时就可以正反两次遍历来记录每一个坑洼处两边的最大值,最后遍历计算面积即可。
奉上代码一:
class Solution {
public:
int trap(vector<int>& height) {
int n=height.size(),res=0;
if(!height.size())
return 0;
vector<int> l(n),r(n);
l[0]=height[0];
for(int i=1;i<n;i++)
l[i]=max(l[i-1],height[i]);
r[n-1]=height[n-1];
for(int i=n-2;i>=0;i--)
r[i]=max(r[i+1],height[i]);
for(int i=0;i<n;i++)
res+=min(l[i],r[i])-height[i];
return res;
}
};
2.方法一:双指针
双指针思路:
双指针的具体思路是使用两根指针分别指向序列头和序列尾,由于接到雨水的量是由一个坑洼处最低的边界决定的,所以我们要让两头指针中最低的那一端向内移动去寻找更高点(不然接雨水的量永远都被最低端限制,无法增加),倘若左指针小于右指针,我们首先要找到左边的最大值,否则不能接到雨水,然后我们往下面逐步遍历低洼处,逐步计算面积,右指针大于左指针时情况也是相同的。
奉上代码二:
class Solution {
public:
int trap(vector<int>& height) {
int l=0,r=height.size()-1;
int l_max=0,r_max=0,res=0;
while(l<r)
{
if(height[l]<=height[r])
{
if(height[l]>=l_max)
l_max=height[l];
else
res+=l_max-height[l];
l++;
}
else
{
if(height[r]>=r_max)
r_max=height[r];
else
res+=r_max-height[r];
r--;
}
}
return res;
}
};
4.方法三:单调栈
单调栈思路:
对于每一个坑洼处我们也可使用单调栈的思想来求解,由于栈中的元素是从栈底到栈顶是递减排列的,这时如果栈中元素数量大于两个,这时如果新元素大于栈顶元素,此时一定能形成一个坑洼来积水,最后逐步计算面积就可以了。
奉上代码三:
class Solution {
public:
int trap(vector<int>& height) {
int res=0;
stack<int> s;
for(int i=0;i<height.size();i++)
{
while(!s.empty()&&height[i] > height[s.top()])
{
int top=s.top();
s.pop();
if(s.empty())
break;
int l=s.top();
res+=(i-l-1)*(min(height[l],height[i])-height[top]);
}
s.push(i);
}
return res;
}
};