和前面的题不同,因为题目要求接雨水,也就是两个柱子之间要形成凹型,因此我们不仅要看当前元素和当前栈顶的元素,还要看栈顶下面的一个元素,以此才能构成凹型来接雨水
AC代码:
class Solution {
public:
int trap(vector<int>& height) {
int n = height.size();
int res = 0;
// s单调递减
// 以s.top()为底,看其左右两边
// 因为s单调递减,所以当遇到新的height[i] > height[s.top()]时
// 如果s.size() > 1,那么s.top()的左边有高于它的柱子,右边也有,
// 那么就能形成凹型,可以接雨水
stack<int> s;
for (int i = 0; i < n; ++i) {
while (!s.empty() && height[i] > height[s.top()]) {
int bottom = height[s.top()];
s.pop();
if (!s.empty()) {
int w = i - s.top() - 1;
int h = min(height[i], height[s.top()]) - bottom;
res += w * h;
}
}
s.push(i);
}
return res;
}
};
和42. 接雨水非常类似,不过从单调递减改为记录单调递增,这样我们才能求以当前栈顶元素为高的矩形的最大面积,底就是两边小于当前栈顶元素矩形的下标中间的距离;注意处理栈为空时候,底就是i,因为只剩下一个元素代表他就是遍历到i时0-i中最小的元素,因此,以i位置为高的矩形的底就可以取整段i长度。
这里不能先在栈push一个-1来统一处理所有情况,因为我们要用s.top()查询heights[s.top()],s中不能有负数。
class Solution {
public:
int largestRectangleArea(vector<int>& heights) {
int n = heights.size();
int res = 0;
// s递增
stack<int> s;
for (int i = 0; i < n; ++i) {
while (!s.empty() && heights[i] < heights[s.top()]) {
int h = heights[s.top()];
s.pop();
if (!s.empty()) {
int w = i - s.top() - 1;
res = max(res, w * h);
} else {
res = max(res, i * h);
}
}
s.push(i);
}
while (!s.empty()) {
int h = heights[s.top()];
s.pop();
if (!s.empty()) {
int w = n - s.top() - 1;
res = max(res, w * h);
} else {
res = max(res, n * h);
}
}
return res;
}
};