给定 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/trapping-rain-water
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解:在51nod上做过类似的题,所以1A。首先明确每根柱子可以尝试去做凹坑的左边,那么,只需要找到凹坑的右边最优柱子即可。右边柱子有两种情况:
假设:左边柱子A;右边柱子B
情况一:B要大于等于A的高度,才有可能形成凹坑
3 2 2 4 2 3
A B
情况二:B小于A的高度,但是B柱子是A柱子右边所有柱子的最高的那一个
5 3 3 3 4 2 3
A B
整体复杂度O(N)
class Solution {
public:
int fun(vector<int>& a,int x,int y){
int d = min(a[x],a[y]),ans = 0;
for(int i=x+1;i<y;i++) ans += d-a[i];
return ans;
}
int trap(vector<int>& a) {
int len = a.size();
if(!len) return 0;
vector<int>maxx;
for(int i=0;i<len;i++) maxx.push_back(a[i]);
// 查找右边最大值的下标
int x = maxx[len-1],y = len-1;
maxx[len-1] = len;
for(int i=len-2;i>=0;i--){
int xx = x,yy = y;
if(x<=maxx[i]){
xx = maxx[i],yy = i;
}
maxx[i] = y;
x = xx; y = yy;
}
// 查找右边第一个比a[i]大的下标
vector<int>r(len);
stack<int>s;
for(int i=len-1;i>=0;i--){
while(s.size()&&a[s.top()]<a[i]) s.pop();
if(s.size()) r[i] = s.top();
else r[i] = len;
s.push(i);
}
int i = 0,ans = 0;
while(i < len){
if(!a[i]){ i++; continue; }
int j = i;
if(r[i] == len) j = maxx[i];
else j = r[i];
if(j == len) break;
ans += fun(a,i,j);
i = j;
}
return ans;
}
};