方法一:辅助栈
核心思想
普通栈的 函数的复杂度为,满足题目要求。但获取栈最小值的 函数需要遍历整个栈,复杂度为,所以本题的主要目的就在于优化对栈的最小值的获取,这可以通过使用一个具有单调性的辅助栈来实现。
具体思路:
数据栈:数据栈用于存储所有元素,保证函数的正常逻辑。
辅助栈:辅助栈中存储数据栈中所有降序的元素。栈具有先进后出的特点,所以一个值压入栈中后,只要未被弹出,所有在它之后进行压栈的小于该值的元素都不会成为最小值,可以不压入辅助栈,这可以保证辅助栈栈顶即为数据栈中所有数据中的最小值。

函数说明: 压栈时,只有辅助栈为空,或该数值不大于辅助栈栈顶元素,才对辅助栈进行压栈。 出栈时,如果数据栈栈顶元素与辅助栈栈顶元素相等,说明该数值被弹出,也需要同时对辅助栈进行出栈。
核心代码

class Solution {
private:
    stack<int> sk;
    stack<int> help;
public:
    void push(int value) {
        sk.push(value);
        //保证辅助栈的单调性
        if(help.empty() || value <= help.top()) {
            help.push(value);
        }
    }
    void pop() {
        //如果辅助栈栈顶值与数据栈栈顶值相等则出栈
        if(help.top() == sk.top()) {
            help.pop();
        }
        sk.pop();
    }
    int top() {
        return sk.top();
    }
    int min() {
        return help.top();//辅助栈栈顶既为最小值
    }
};

复杂度分析
时间复杂度:,对单个操作,四个函数的时间复杂度均为常数级别
空间复杂度:,最坏情况下,辅助栈也需要存储所有元素,使用空间

方法二:单个栈
核心思想
也可以使用单个栈完成功能,但此时的栈不是存储数据,而是存储数据与当前最小值的差值,并另外存储一个最小值
函数说明: :压栈时,当栈为空时,存储最小值,压入差值0。栈不为空时,压入数据与当前最小值的差值,如果差值为负,则更新最小值 :出栈时,如果此时栈顶值为负数,说明此处发生的最小值的变化,需要更新最小值。 :如果栈顶值为负数,说明最小值在此处更新,此时返回最小值即可。如果栈顶值为正数,即为最小值与数据的差值,相加后进行返回 :直接返回存储的最小值即可
核心代码

class Solution {
private:
    stack<long> sk;//记录与最小值差值,由于可能大于INT_MAX,使用long
    long tmin;//记录最小值
public:
    void push(int value) {
        if(sk.empty()) {
            //当栈为空,最小值即为当前值,差值为0
            sk.push(0);
            tmin = value;
        } else {
            //压入与最小值的差值
            sk.push(value - tmin);
            if(value < tmin) {
                //如果当前值小于最小值,进行更新
                tmin = value;
            }
        }
    }

    void pop() {
        if(sk.top() < 0) {
            //差值为负数,说明当前位置最小值发生改变,需要改回该元素压入前的最小值
            tmin -= sk.top();
        }
        sk.pop();
    }

    int top() {
        if(sk.top() < 0) {
            return tmin;//此时最小值刚进行更新
        } else {
            return tmin + sk.top();
        }
    }
    int min() {
        return tmin;
    }
};

复杂度分析
时间复杂度:,对单个操作,四个函数的时间复杂度均为常数级别
空间复杂度:,只使用了常数个变量