题目描述:
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.
For example,
Given [0,1,0,2,1,0,1,3,2,1,2,1]
, return 6
.
思路:短板效应,能乘多少水取决于短的那个板。当高度发生降低时,将降低前的桩入栈作为凹槽前桩,当高度发生升高时将升高后的桩作为凹槽的后桩。整个过程就是一直找前后桩的对应。
class Solution {
public:
bool findSame(int num,stack<int> index)
{
if(!index.empty())
if(num==index.top())
return false;
return true;
}
int trap(vector<int>& height)
{
if(height.empty())
return 0;
//存放可以作为前桩的下标,该栈保存的下标不断更新为一个递减序列,因为出现大于等于前桩的后桩,该桩就无法继续作为后续凹槽的前桩,所以要出栈
stack<int> index;
int Area = 0;
for(int i=1;i<height.size();i++)
{
//遇到前桩入栈 ,findSome防止前后都比该元素低的情况重复入栈
if(height[i]<height[i-1]&&findSame(i-1,index))
{
index.push(i-1);
}
else
{
//对后桩的处理
if(height[i]>height[i-1])
{
int endStake = i;
//如果后桩比前桩低那么能存水的面积就是前后桩的距离乘以后桩与平地的高度差
if(!index.empty()&&height[endStake]<height[index.top()])
{
Area += (height[endStake]-height[endStake-1])*(endStake-index.top()-1);
}
else
{
bool flag = false;
int midStake = 0;
//如果后桩比前桩高那么就不断求前桩与后桩之间的积水面积
//并将前桩出栈因为后桩更高,前桩无法再充当积水槽,直到后桩小于等于前桩,最后将后桩入栈作为下一个凹槽的前桩
//求后桩与前桩存水的面积时要注意除了第一次高度差是前桩减去平地差之外
//在之后的计算中由于上一个前桩与后桩的积水面积已经被计算在总面积之内,所以高度差是目前前桩与上一个前桩之差
while(!index.empty()&&height[endStake]>height[index.top()])
{
int width = endStake-index.top()-1;
int length;
if(!flag)
{
length = height[index.top()]-height[endStake-1];
}
else
{
length = height[index.top()]-height[midStake];
}
flag = true;
midStake = index.top();
Area += width*length;
index.pop();
}
//如果栈中还剩余桩时,那么后桩必定小于等于前桩,求前后桩之间的存水面积
if(!index.empty())
{
int width = endStake-index.top()-1;
int length;
if(!flag)
{
length = height[endStake]-height[endStake-1];
}
else
{
length = height[endStake]-height[midStake];
}
Area += width*length;
//如果后桩和前桩一样高将前桩出栈,因为前后桩一样高,前桩无法再充当积水槽
if(height[endStake]==height[index.top()])
index.pop();
}
}
index.push(endStake);
}
}
// cout<<i<<" "<<Area<<endl;
}
return Area;
}
};