本文记录作者刷题过程中与栈相关的题目。

一、设计最小栈

剑指 Offer 30. 包含min函数的栈(中等函数)

155. 最小栈(简单难度)

面试题 03.02. 栈的最小值(简单难度)

class MinStack {
public:
    stack<int> stack1;//正常栈,实现栈的正常功能
    stack<int> stack2;//辅助栈,负责实现min函数,入栈时只入比自己栈顶元素小的元素,出栈时和当前元素相等就出栈
    MinStack() {}
    // 入栈
    void push(int val) {
        stack1.push(val);//正常入栈
        // 如果辅助栈为空或者辅助栈栈顶元素比较大,就入栈
        if(stack2.empty()||stack2.top()>=val)stack2.push(val);
    }
    // 出栈
    void pop() {
        int top=stack1.top();
        stack1.pop();// 正常出栈
        // 如果出栈的元素和辅助栈栈顶元素相等
        if(top==stack2.top()) stack2.pop();
    }
    // 获取栈顶元素
    int top() {
        return stack1.top();//正常的栈顶元素
    }
    // 获取最小值
    int getMin() {
        return stack2.top();//辅助栈的栈顶元素
    }
};

二、验证栈序列

剑指 Offer 31. 栈的压入、弹出序列

946. 验证栈序列(中等难度)

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
        stack<int> stk;
        int i=0;
        for(int x:pushed){
            stk.push(x);
            // 循环检查,如果栈顶元素和出栈队列元素相同就出栈
            // 栈内元素用完就继续加
            while(!stk.empty()&&stk.top()==popped[i]){
                stk.pop();
                i++;
            }
        }
        return stk.empty();
    }
};

三、单调栈

剑指 Offer II 039. 直方图最大矩形面积

84. 柱状图中最大的矩形

class Solution {
public:
    /*本题也是一套经典题目,题目容易理解,难点在于分析什么时候勾勒的矩形面积最大?
    思路:
    假设我们考察其中一个柱子,它所能勾勒出的最大矩形面积由左侧柱子和右侧柱子的高度决定:
    若左柱子的高度>当前考察的柱子高度,则向左扩张一个柱子,直至左侧柱子高度<当前柱子高度||左侧无柱子
    若右柱子的高度>当前考察的柱子高度,则向右扩张一个柱子,直至右侧柱子高度<当前柱子高度||右侧无柱子
    此时最大矩形面积=当前柱子的高度*左右最远柱子间的距离
    单调栈的简单思路讲解:https://blog.csdn.net/Zolewit/article/details/88863970*/
    int largestRectangleArea(vector<int>& heights) {
        int res=0;//最大面积
        int n=heights.size();
        // 在原数组左右两侧添加一个0
        vector<int> height(n+2,0);
        for(int i=1;i<n+1;i++){
            height[i]=heights[i-1];
        }
        stack<int> stk;// 单调栈,保存元素索引
        for(int i=0;i<n+2;i++){
            // 当前入栈元素为height[i],将栈中所有比height[i]大的元素出栈
            while(!stk.empty()&&height[i]<height[stk.top()]){
                // 出栈
                int index=stk.top();
                stk.pop();
                // 此时,height[index]的下一个更小元素是height[i],上一个更小元素是height[stk.top()]
                int hig=height[index];//高=height[index],其随着出栈而不断变化
                int wid=i-stk.top()-1;//宽=[stk.top(),i]=i-stk.top()-1,右边界是定值,左边界是变量
                res =max(res,hig*wid);//完全覆盖第index个柱子的最大矩形的面积
            }
            stk.push(i);
        }
        return res;
    }
};

85. 最大矩形

剑指 Offer II 040. 矩阵中最大的矩形

class Solution {
public:
    /*每一层看作是柱状图,可以套用84题柱状图的最大面积。
    第一层柱状图的高度["1","0","1","0","0"],最大面积为1;
    第二层柱状图的高度["2","0","2","1","1"],最大面积为3;
    第三层柱状图的高度["3","1","3","2","2"],最大面积为6;
    第四层柱状图的高度["4","0","0","3","0"],最大面积为4;*/
    int maximalRectangle(vector<vector<char>>& matrix) {
        if (matrix.size() == 0 || matrix[0].size() == 0) {
            return 0;
        }
        int col = matrix.size();
        int row = matrix[0].size();
        vector<int>heights(row);
        int ans = 0;
        for (int i = 0; i < col; i++) {
            for (int j = 0; j < row; j++) {
                if (matrix[i][j] == '1') {
                    heights[j] += 1;
                } else {
                    heights[j] = 0;
                }
            }
            ans = max(ans, largestRectangleArea(heights));
        }
        return ans;
    }
    int largestRectangleArea(vector<int>& heights) {
        int res=0;//最大面积
        int n=heights.size();
        // 在原数组左右两侧添加一个0
        vector<int> height(n+2,0);
        for(int i=1;i<n+1;i++){
            height[i]=heights[i-1];
        }
        stack<int> stk;// 单调栈,保存元素索引
        for(int i=0;i<n+2;i++){
            // 当前入栈元素为height[i],将栈中所有比height[i]大的元素出栈
            while(!stk.empty()&&height[i]<height[stk.top()]){
                // 出栈
                int index=stk.top();
                stk.pop();
                // 此时,height[index]的下一个更小元素是height[i],上一个更小元素是height[stk.top()]
                int hig=height[index];//高=height[index],其随着出栈而不断变化
                int wid=i-stk.top()-1;//宽=[stk.top(),i]=i-stk.top()-1,右边界是定值,左边界是变量
                res =max(res,hig*wid);//完全覆盖第index个柱子的最大矩形的面积
            }
            stk.push(i);
        }
        return res;
    }
};