单调栈。从栈底到栈顶依次减小,如果入栈的元素大于等于栈顶元素,则将栈顶弹出并进行结算。
每次结算时,雨水的高度为让他弹出的元素与弹出他之后的栈顶元素中的较小值与他的差,长度就是让他弹出的元素的位置与弹出他之后的栈顶元素位置之差减1.
如:[1, 0, 2]
,栈顶为0,此时2要入栈,但是2比0大,则将0弹出,并结算,高度为min(1,2)-0
,长度为2的下标 - 1的下标 - 1
.
- C++
class Solution {
public:
//单调栈:维护一个单调递减的栈
//如果要入栈的元素比栈顶元素大,则将栈顶元素弹出并结算
int trap(vector<int>& height) {
if(height.size() == 0) return 0;
stack<int> s;
int res = 0;
for(int i = 0; i < height.size(); i++){
while(!s.empty() && height[i] > height[s.top()]){
int tmp = s.top();
s.pop();
int h = s.empty() ? 0 : min(height[s.top()], height[i]) - height[tmp];
int w = s.empty() ? 0 : i - s.top() - 1;
res += h * w;
}
s.push(i);
}
return res;
}
};
- Go版本
func trap(height []int) int {
if len(height) == 0 {
return 0
}
var s []int
res := 0
for i := 0; i < len(height); i++ {
for len(s) > 0 && height[i] > height[s[len(s)-1]] {
tmp := s[len(s)-1]
s = s[:len(s)-1]
if len(s) != 0 {
var h int
if height[i] < height[s[len(s)-1]] {
h = height[i] - height[tmp]
} else {
h = height[s[len(s)-1]] - height[tmp]
}
w := i - s[len(s)-1] - 1
res += h * w
}
}
s = append(s, i)
}
return res
}