算法训练1-day41-单调栈

29 阅读1分钟
  1. 42. 接雨水

和前面的题不同,因为题目要求接雨水,也就是两个柱子之间要形成凹型,因此我们不仅要看当前元素和当前栈顶的元素,还要看栈顶下面的一个元素,以此才能构成凹型来接雨水

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;
    }
};
  1. 84. 柱状图中最大的矩形

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;
    }
};