LeetCode-155. Min Stack

Description

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
    push(x) -- Push element x onto stack.
    pop() -- Removes the element on top of the stack.
    top() -- Get the top element.
    getMin() -- Retrieve the minimum element in the stack.

Example

MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin();   --> Returns -3.
minStack.pop();
minStack.top();      --> Returns 0.
minStack.getMin();   --> Returns -2.

Solution 1(C++)

class MinStack {
    stack<int> s;
public:
    /** initialize your data structure here. */
    MinStack() {

    }

    void push(int x) {
        s.push(x);
    }

    void pop() {
        s.pop();
    }

    int top() {
        return s.top();
    }

    int getMin() {
        stack<int> ss;
        int Min=INT_MAX;
        while(!s.empty()){
            ss.push(s.top());
            Min=min(Min, s.top());
            s.pop();
        }
        while(!ss.empty()){
            s.push(ss.top());
            ss.pop();
        }
        return Min;
    }
};

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

Solution 2(C++)

static int x = []() { std::ios::sync_with_stdio(false); cin.tie(NULL); return 0; }();
class MinStack {
    long long min;
    stack<long long>l;
public:
    MinStack() { 
        min = INT_MIN; 
    }

    void push(int x) { 
        if (l.empty()) {
            l.push(0); min = x; 
        } else {
            l.push(x - min); 
            if (x < min) {
                min = x; 
            } 
        } 
    };

    void pop() {
        if (!l.empty()) {
            long long t = l.top(); l.pop();
            if (t < 0) {
                min -= t; 
            } 
        } 
    };

    int top() const {
        if (l.empty()) {
            return INT_MIN; 
        } 
        long long t = l.top();
        return (int) (t < 0 ? min : min + t); };

    int getMin() const {
        return (int)min; 
    };
};

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

Solution 3(C++)

class MinStack {
private:
    stack<int> s1;
    stack<int> s2; //s2用来存放较小值,插入者若小于s2的栈顶,则放入作为新的最小值处理;
public:
    void push(int x) {
        s1.push(x);
        if (s2.empty() || x <= getMin())  s2.push(x);       
    }
    void pop() {
        if (s1.top() == getMin())  s2.pop();
        s1.pop();
    }
    int top() {
        return s1.top();
    }
    int getMin() {
        return s2.top();
    }
};

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

算法分析

这一道题中我更新了三种方法,其中,解法一是我自己最开始写的,用时超级长···,解法二是大神的最快解法,解法三是我后来想改进的,但是被我自己否定掉,我认为有逻辑漏洞,但是是解法人数最多,用时较快的。

解法一就不啰嗦了。

解法二目前看不懂。

解法三主要说一下我自己认为的漏洞,我当时想的是:由于pop()函数中,删除s1的栈顶,如果s1的栈顶也是s2的栈顶,那么s2的栈顶也会删除掉,其实就是s1的栈顶是目前的最小值,那么s2也要更新。但是s1的栈顶不是最小值的话,那么s2不用更新。

我当时就觉得有问题啊,因为,pop()函数执行多次,s1的栈顶不是最小值,但是s2的次小值,举个例子:s1:(4,3,1,2),对应s2:(4,3,2,1)。那么我删除s1的栈顶2,s2不更新,再删除s1的栈顶1,s2也删除栈顶,这时,s2 的栈顶就是2了,但是2已经在第一次s1的pop操作中,就删除了。

后来,仔细一想,你就会发现我这个漏洞根本就不会出现,因为,这与栈的特性有关。其实s2根本就不是(4,3,2,1)。重新回顾一下push()函数中的算法,就会发现,其实2根本没有插入s2中,s2其实是(4,3,1)。因为在s1push1之后,s2的栈顶就是1,这时s1push 2,s2栈顶是1,2 > 1,那么2不会插入s2。

所以解法三是可行的。

程序分析

程序分析的部分着重分析一下解法二,一开始就是用了lamda表达式,可以参考: C++—— Lambda表达式

大概能明白解法二的意思,这个stack储存的不是输入的值,而是处理过的,储存的是与最小值相差的值。但是要注意这个结构中会有负数,因为最小值的更新是在push之后完成的。

但是为什么要在开头加这样一句话,我还是不太明白的。目前有关这句话找到的资料是:ios::sync_with_stdio(false);

虽然不太明白个别几句,但是这种想法还是值得学习的,那就是不要被禁锢住,只要满足输入与输出就可以了。不是说stack里都要储存要属于的值,可以在中间加一个映射,也许会帮助解决很多问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值