LintCode 12: Min Stack (数据结构经典题)

  1. Min Stack
    Implement a stack with min() function, which will return the smallest number in the stack.

It should support push, pop and min operation all in O(1) cost.

Example
push(1)
pop() // return 1
push(2)
push(3)
min() // return 2
push(1)
min() // return 1
Notice
min operation will never be called if there is no number in the stack.

代码如下:
注意:

  1. pop()完之后要注意stack为空的情况。如果为空,重新将min_num设为INT_MAX;
  2. 如果pop()掉了min_num,要注意stack中是否还有多余的min_num。所以这里必须用map来记录每个数出现频数。
class MinStack {
public:
    MinStack() : min_num(INT_MAX) {
        // do intialization if necessary
    }

    /*
     * @param number: An integer
     * @return: nothing
     */
    void push(int number) {
        s.push(number);
        if (number < min_num) {
            min_num = number;
            mp[number] = 1;
        } else if (number == min_num) {
            mp[number]++;
        }
    }

    /*
     * @return: An integer
     */
    int pop() {
        if (!s.empty()) {
            int topNum = s.top();
            s.pop();
            if (topNum == min_num) {
                if (mp[topNum] == 1) {
                    mp.erase(topNum);
                    if (!mp.empty())
                        min_num = mp.begin()->first;
                    else
                        min_num = INT_MAX;
                } else {
                    mp[topNum]--;
                }
            }
            return topNum;
        }
    }

    /*
     * @return: An integer
     */
    int min() {
        return min_num;
    }

private:
    stack<int> s;
    int min_num;
    unordered_map<int, int> mp;  //num, freq
};

二刷:

class MinStack {
public:
    MinStack() {
        minElem = INT_MAX;
    }

    /*
     * @param number: An integer
     * @return: nothing
     */
    void push(int number) {
        s.push(number);
        if (mp.find(number) == mp.end()) {
            mp[number] = 1;   
        } else {
            mp[number]++;
        }
        minElem = std::min(minElem, number);
    }

    /*
     * @return: An integer
     */
    int pop() {
        if (!s.empty()) {
            int topElem = s.top();
            s.pop();
            
            if (mp[topElem] == 1) {
                mp.erase(topElem);
                if (mp.empty()) {
                    minElem = INT_MAX;
                } else {
                    minElem = mp.begin()->first;
                }
            } else {
                mp[topElem]--;
            }

            return topElem;
        }
    }

    /*
     * @return: An integer
     */
    int min() {
        return minElem;
    }
private:
    stack<int> s;
    map<int, int> mp;  //number, count
    int minElem;
};

上面用到了map,似乎应该改为unordered_map才满足O(1)的时间复杂度

解法3:用两个栈。其中minStk的top保存对应到dataStk的top的最小值。

class MinStack {
public:
    MinStack() {
        // do intialization if necessary
    }

    /*
     * @param number: An integer
     * @return: nothing
     */
    void push(int number) {
        dataStk.push(number);
        if (number < minV) minV = number;
        minStk.push(minV);
    }

    /*
     * @return: An integer
     */
    int pop() {
        int dataStkTop = dataStk.top();
        int minStkTop = minStk.top();
        dataStk.pop();
        minStk.pop();
        
        if (minStk.empty()) {
            minV = INT_MAX;
        } else if (minV == minStkTop) {  //important fix
            minV = minStk.top();         //!!!
        }

        return dataStkTop;
    }

    /*
     * @return: An integer
     */
    int min() {
        return minStk.top();
    }
private:
    stack<int> dataStk;
    stack<int> minStk;
    int minV = INT_MAX;
};

注意下面的fix很重要

else if (minV == minStkTop) {  //important fix
            minV = minStk.top();         //!!!
        }

注意当minStk执行pop()之后,因为minStk之前的top可能就是minV,所以minV会不准,这是我们要把minV更新到minStk的现在的top。
一个例子是
push(24)
min()
push(20)
min()
pop()
min()
push(24)
min()

具体执行流程
dataStk push 24 minStak push 24
minStk.top() = 24
dataStk push 20 minStak push 20
minStk.top() = 20
dataStk pop 20 minV = 20
minStk.top() = 24
dataStk push 24 minStak push 20
minStk.top() = 20

输出结果:
Output Data
[24,20,20,24,20]

Expected
[24,20,20,24,24]
即最后一个pop()操作后,minV还是20,应该调整到minStk.top(),也就是24才对。

又改进了一下,minStk并不需要每次都跟dataStk一样同步push和pop,只有当dataStk要push的元素<=minV时,我们才push它到minStk。也只有当pop出来的元素刚好跟当前的minV相等时,我们才pop minStk,并相应调整minV。这样minStk的大小可以相对小一些。

class MinStack {
public:
    MinStack() {
        // do intialization if necessary
    }

    /*
     * @param number: An integer
     * @return: nothing
     */
    void push(int number) {
        dataStk.push(number);
        if (number <= minV) {
            minV = number;
            minStk.push(minV);
        }
    }

    /*
     * @return: An integer
     */
    int pop() {
        int dataStkTop = dataStk.top();
        int minStkTop = minStk.top();
        dataStk.pop();
        
        if (minV == dataStkTop) {
            minStk.pop();
            if (minStk.empty()) minV = INT_MAX;
            else minV = minStk.top();
        }
       
        return dataStkTop;
    }

    /*
     * @return: An integer
     */
    int min() {
        return minStk.top();
    }
private:
    stack<int> dataStk;
    stack<int> minStk;
    int minV = INT_MAX;
};

又优化了一下,根本就没有必要维护minV,因为minStk.top()就是minV。注意push的时候要考虑minStk为空和number <= minStk.top()两种情况。

class MinStack {
public:
    MinStack() {
        // do intialization if necessary
    }

    /*
     * @param number: An integer
     * @return: nothing
     */
    void push(int number) {
        dataStk.push(number);
        if (minStk.empty() || number <= minStk.top()) {
            minStk.push(number);
        }
    }

    /*
     * @return: An integer
     */
    int pop() {
        int dataStkTop = dataStk.top();
        int minStkTop = minStk.top();
        dataStk.pop();
        if (minStkTop == dataStkTop) {
            minStk.pop();
        }
       
        return dataStkTop;
    }

    /*
     * @return: An integer
     */
    int min() {
        return minStk.top();
    }
private:
    stack<int> dataStk;
    stack<int> minStk;
};

五刷:Leetcode 155. 题目差不多,稍有不同。
这个版本不如上面的好,minStk的空间没有得到优化。

class MinStack {
public:
    MinStack() {
        minVal = INT_MAX;
    }
    
    void push(int val) {
        genStk.push(val);
        minVal = min(minVal, val);
        minStk.push(minVal);
    }
    
    void pop() {
        genStk.pop();
        minStk.pop();
        if (!minStk.empty()) minVal = minStk.top();
        else minVal = INT_MAX;
    }
    
    int top() {
        return genStk.top();
    }
    
    int getMin() {
        return minStk.top();
    }
private:
    stack<int> genStk, minStk;
    int minVal;
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(val);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

稍微优化一下,因为没必要维护minVal, minStk.top()就是minVal。

class MinStack {
public:
    MinStack() {
    }
    
    void push(int val) {
        genStk.push(val);
        if (minStk.empty()) minStk.push(val);
        else minStk.push(min(val, minStk.top()));
    }
    
    void pop() {
        genStk.pop();
        minStk.pop();
    }
    
    int top() {
        return genStk.top();
    }
    
    int getMin() {
        return minStk.top();
    }
private:
    stack<int> genStk, minStk;   
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值