42. Trapping Rain Water
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.
The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!
题意:
给出非负整数,表示柱状图的高度,在这里每个柱的宽度为1,计算可以收集多少雨水。
如图的例子可以看出怎么存储雨水的。
方法一:
思路:
先从左侧开始向右侧开始遍历数组,用一个队列preVec来存储比队列头小的元素值,当遍历出现比队列头大的元素时,此时队列头比队列中其余元素大的值就是所收集的雨水,直接相加,然后更新队列头元素,继续遍历,直到遍历数组结束,此时如果preVec中还有元素表明preVec队列头比后面元素都大,但是不确定preVec中的元素能收集多少雨水,所以重新按照上面的思路从队列preVec尾到头遍历,求出所存储的雨水。代码如下(此代码效率不高):
class Solution {
public:
int trap(vector<int>& height) {
if(height.size()<=2)
return 0;
int sum = 0;
deque<int> preVec;
for(int i = 0;i < height.size();i++)
{
if(preVec.empty() || height[i]<preVec[0])
{
preVec.push_back(height[i]);
}
else
{
while(!preVec.empty())
{
sum += preVec[0] - preVec.back();
preVec.pop_back();
}
preVec.push_back(height[i]);
}
}
deque<int> lastVec;
for(int i = preVec.size()-1;i>=0;i--){
if(lastVec.empty() || preVec[i]<lastVec[0])
{
lastVec.push_back(preVec[i]);
}
else
{
while(!lastVec.empty())
{
sum += lastVec[0] - lastVec.back();
lastVec.pop_back();
}
lastVec.push_back(preVec[i]);
}
}
return sum;
}
};
方法二:
思路:
采用left和right两个指针,维护装水两边的位置,这道题最主要的就是两边往中间遍历。
当left处高度低时,说明left右侧装的水肯定和left处一样高,此时逐步右移left,同是记录当前第二高点secHeight,加上left处与右移后位置高度差(因为这里都能装水啊)即然利用这个第二高点secHeight减去当前历经的柱子,直到再遇到同样高或者更高的位置。然后进行下一轮判断。
同样,当right处高度低时,说明right左侧的水肯定和right处一样高,此时逐步左移right,同是记录当前第二高点secHeight,加上right处与左移后位置高度差,即然利用这个第二高点secHeight减去当前历经的柱子,直到再遇到同样高或者更高的位置。
最后直到left和right相遇,结束。代码如下:
class Solution {
public:
int trap(vector<int>& height) {
if(height.size()<=2)
return 0;
int area=0,secHight=0,left = 0,right = height.size()-1;
while(left<right)
{
if(height[left]<height[right])//控制从左向右计算雨水量
{
secHight = max(height[left],secHight);
area +=(secHight - height[left]);
left++;
}
else//控制从右向左计算雨水量
{
secHight = max(height[right],secHight);
area +=(secHight - height[right]);
right--;
}
}
return area;
}
};