代码随想录算法训练营day60||42. 接雨水 ||84.柱状图中最大的矩形

42. 接雨水

思路:

首先我们确定是使用单调栈的思路,那么使用单调栈的话存放顺序是什么?从栈顶到栈底的存放顺序是从小到大,递增的顺序,当遍历到比栈顶元素大的元素的时候,就进行操作,这样就模拟了一个凹槽,两边大中间小,此时我们计算凹槽能够容纳的面积就是接雨水的面积。单调栈是按照西方向来计算雨水的。

遇到相同高度的柱子怎么办?

遇到相同高度的元素,将原来栈里元素弹出,将新元素入栈。因为我们要求宽度的时候,如果遇到高度相同的柱子,需要使用最右边的柱子来计算宽度。

遍历到小于等于栈顶元素时,就进行压栈操作

class Solution {
public:
    int trap(vector& height) {
        if (height.size() <= 2) return 0; // 可以不加
        stack st; // 存着下标,计算的时候用下标对应的柱子高度
        st.push(0);
        int sum = 0;
        for (int i = 1; i < height.size(); i++) {
            if (height[i] < height[st.top()]) {     // 情况一
                st.push(i);
            } if (height[i] == height[st.top()]) {  // 情况二
                st.pop(); // 其实这一句可以不加,效果是一样的,但处理相同的情况的思路却变了。
                st.push(i);
            } else {                                // 情况三
                while (!st.empty() && height[i] > height[st.top()]) { // 注意这里是while
                    int mid = st.top();
                    st.pop();
                    if (!st.empty()) {
                        int h = min(height[st.top()], height[i]) - height[mid];
                        int w = i - st.top() - 1; // 注意减一,只求中间宽度
                        sum += h * w;
                    }
                }
                st.push(i);
            }
        }
        return sum;
    }
};

84.柱状图中最大的矩形

思路:

本题是找每个柱子左右两边第一个小于该柱子的柱子。这里涉及到了单调栈的重要性质,就是单调栈里的顺序,是从小到大还是从大到小。本题就是从栈顶到栈底从大到小的顺序。

此时大家可以发现其实就是栈顶和栈顶下个元素以及即将入栈的三个元素组成了要求的最大面积和高度。注意:这里的三个元素并不是连续的三个柱子组成的面积!!!

其余的思路与上一题相差不大。

class Solution {
public:
    int largestRectangleArea(vector& heights) {
        stack st;
        heights.insert(heights.begin(), 0); // 数组头部加入元素0
        heights.push_back(0); // 数组尾部加入元素0
        st.push(0);
        int result = 0;
        // 第一个元素已经入栈,从下标1开始
        for (int i = 1; i < heights.size(); i++) {
            // 注意heights[i] 是和heights[st.top()] 比较 ,st.top()是下标
            if (heights[i] > heights[st.top()]) {
                st.push(i);
            } else if (heights[i] == heights[st.top()]) {
                st.pop(); // 这个可以加,可以不加,效果一样,思路不同
                st.push(i);
            } else {
                while (heights[i] < heights[st.top()]) { // 注意是while
                    int mid = st.top();
                    st.pop();
                    int left = st.top();
                    int right = i;
                    int w = right - left - 1;
                    int h = heights[mid];
                    result = max(result, w * h);
                }
                st.push(i);
            }
        }
        return result;
    }
};

你可能感兴趣的:(数据结构)