给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 感谢 Marcos 贡献此图。
示例:
输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6
空间换时间。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/* 暴力超时:
* 直接按问题描述进行。对于数组中的每个元素,
* 我们找出下雨后水能达到的最高位置,
* 等于两边最大高度的较小值减去当前高度的值。
*/
/*
class Solution {
public:
int trap(vector<int>& height) {
int sum = 0;
for(int i=1;i<height.size();i++){
int leftmax = 0;
int rightmax = 0;
int minH = 0;
for(int j=0;j<i;j++){
leftmax = max(leftmax,height[j]);
}
for(int k=i+1;k<height.size();k++){
rightmax = max(rightmax,height[k]);
}
minH = min(leftmax,rightmax)-height[i];
if(minH>0){
sum+=minH;
}
}
return sum;
}
};
*/
/*
* 比暴力解法只优化了一个地方,
* 将每个下标所对应的左边最大值和
* 右最大值提前算出来。
* 之后考虑边界条件:
* 最左边的边界值的最大高为0
* 最右边的边界值的最大高为0
*/
class Solution {
public:
int trap(vector<int>& height) {
if(height.empty() || height.size()==1)
return 0;
vector<int>LMaxArr;
vector<int>RMaxArr;
int LMaxTmp = height[0];
int RMaxTmp = height[height.size()-1];
LMaxArr.push_back(0);
RMaxArr.push_back(0);
int minH = 0;
int sum = 0 ;
for(int i=1;i<height.size();i++){
LMaxTmp = max(LMaxTmp,height[i-1]);
LMaxArr.push_back(LMaxTmp);
}
for(int i=height.size()-2;i>=0;i--){
RMaxTmp = max(RMaxTmp,height[i+1]);
RMaxArr.push_back(RMaxTmp);
}
reverse(RMaxArr.begin(),RMaxArr.end());
for(int i=0;i<height.size();i++){
minH = min(LMaxArr[i],RMaxArr[i])-height[i];
if(minH>0){
sum+=minH;
}
}
return sum;
}
};
int main(){
vector<int>h = {0,2,0};
Solution *ps = new Solution();
cout<<ps->trap(h)<<endl;
return 0;
}