做法1:动态规划来求左边和右边最大值
class Solution {
public:
int trap(vector<int>& height) {
//雨水能达到的最大高度为:左边最大值和右边最大值的最小值的高度
int n = height.size();
vector<int> left_max(n);
vector<int> right_max(n);
left_max[0] = 0;
for (int i = 1; i < n; ++i) {
left_max[i] = max(left_max[i - 1], height[i - 1]);
}
right_max[n - 1] = 0;
for (int i = n - 2; i >= 0; --i) {
right_max[i] = max(right_max[i + 1], height[i + 1]);
}
long long ans = 0;
for (int i = 1; i < n; ++i) {
if (min(left_max[i], right_max[i]) > height[i]) {
ans += (min(left_max[i], right_max[i]) - height[i]);
}
}
return ans;
}
};
做法2:单调栈
class Solution {
public:
int trap(vector<int>& height) {
//维护一个单调递减的栈,如果小于等于栈顶入栈,
//如果大于栈顶,则不断出栈一个元素 :
// 如果栈不为空:宽度×高度就是当前层加的高度,ans+=
// 如果栈为空,将该元素入栈
int ans = 0;
int n = height.size();
vector<int> stk(n);
int top = -1;
for (int i = 0; i < n; ++i) {
while (top != -1 && height[i] > height[stk[top]]) {
int tmp = stk[top];
--top;
if (top != -1) {
int _min = min(height[i], height[stk[top]]);
ans += (i - stk[top] - 1) * (_min - height[tmp]);
}
}
stk[++top] = i;
}
return ans;
}
};
难点:
int _min = min(height[i], height[stk[top]]);
ans += (i - stk[top] - 1) * (_min - height[tmp]);
由于是一个单调递减的栈,所以雨水是一层一层的计算到的。