从零开始的LC刷题(36)*: Min Stack 输出最小值的栈与其优化

本文探讨了如何设计一个支持常数时间复杂度内完成push、pop、top和获取最小元素操作的栈。通过尝试链栈、数组栈和vector容器,最终采用缓存最小值的策略,显著提高了运行时间和内存效率。在push时确定最小值,在pop后更新缓存,避免每次push时排序,实现了高效解决方案。

原题:

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.

 

就是编写一个栈的代码实现例子里的功能,先用链栈,结果:

Success

Runtime: 192 ms, faster than 5.27% of C++ online submissions for Min Stack.

Memory Usage: 17.1 MB, less than 16.38% of C++ online submissions for Min Stack.

代码:

class MinStack {
public:
    /** initialize your data structure here. */
    struct Stack{
        int val;
        Stack *next;
        Stack(int x):val(x),next(NULL){}
    };
    Stack *head=new Stack(INT_MAX);
    MinStack() {
        
    }
    
    void push(int x) {
        Stack *s=new Stack(x);
        s->next=head->next;
        head->next=s;
    }
    
    void pop() {
        Stack *s=head->next;
        head->next=s->next;
        delete(s);
    }
    
    int top() {
        return head->next->val;
    }
    
    int getMin() {
        int i=INT_MAX;
        Stack *j=head->next;
        while(j!=NULL){
            if(j->val<i){i=j->val;}
            j=j->next;
        }
        return i;
    }
};

/**
 * 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();
 */

可以看出来性能并不好,打算用数组栈试试:

Success

Runtime: 192 ms, faster than 5.27% of C++ online submissions for Min Stack.

Memory Usage: 17.8 MB, less than 5.01% of C++ online submissions for Min Stack.

代码:

class MinStack {
public:
    /** initialize your data structure here. */
    int Stack[65536];
    int head=0;
    MinStack() {
        
    }
    
    void push(int x) {
        Stack[head++]=x;
    }
    
    void pop() {
        head--;
    }
    
    int top() {
        return Stack[head-1];
    }
    
    int getMin() {
        int r=INT_MAX;
        int i=head;
        while(i>0){
            if(Stack[i-1]<r){r=Stack[i-1];}
            i--;
        }
        return r;
    }
};

/**
 * 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();
 */

还是不行,只能使用vector容器了:

Success

Runtime: 200 ms, faster than 5.27% of C++ online submissions for Min Stack.

Memory Usage: 17 MB, less than 46.46% of C++ online submissions for Min Stack.

代码:

class MinStack {
public:
    /** initialize your data structure here. */
    vector<int> Stack;
    MinStack() {
        
    }
    
    void push(int x) {
        Stack.push_back(x);
    }
    
    void pop() {
        Stack.pop_back();
    }
    
    int top() {
        return Stack.back();
    }
    
    int getMin() {
        return *min_element(Stack.begin(),Stack.end());
    }
};

/**
 * 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();
 */

还是不行,哭哭惹,感觉是求最小值占了大量时间,想了想肯定是做题这帮比在push的时候就排序了,但是又懒得打那么多代码,最后决定用一个int缓存存储最小值,在输入的时候确定是多少,在pop最小值后失效,需要在输出最小值的时候遍历一遍并且使缓存重新生效,结果:

Success

Runtime: 28 ms, faster than 97.14% of C++ online submissions for Min Stack.

Memory Usage: 16.8 MB, less than 91.22% of C++ online submissions for Min Stack.

代码:

class MinStack {
public:
    /** initialize your data structure here. */
    vector<int> Stack;
    int min=INT_MAX;
    bool v=true;
    MinStack() {
        
    }
    
    void push(int x) {
        if (x<=min){
            min=x;}
        Stack.push_back(x);
    }
    
    void pop() {
        int i=Stack.back();
        Stack.pop_back();
        if(i==min){v=false;}
    }
    
    int top() {
        return Stack.back();
    }
    
    int getMin() {
        if(v){return min;}
        min=*min_element(Stack.begin(),Stack.end());
        v=true;
        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();
 */

可以看出来情况好了很多,也可以使用计数缓存来存储多次出现的最小值:

class MinStack {
public:
    /** initialize your data structure here. */
    vector<int> Stack;
    int min[2]={INT_MAX,0};//计数器cache
    MinStack() {
        
    }
    
    void push(int x) {
        if (x<min[0]){
            min[0]=x;min[1]=1;}
        else if(x==min[0]){min[1]++;}
        Stack.push_back(x);
    }
    
    void pop() {
        int i=Stack.back();
        Stack.pop_back();
        if(i==min[0]){min[1]--;}
    }
    
    int top() {
        return Stack.back();
    }
    
    int getMin() {
        if(min[1]>0){return min[0];}
        min[0]=*min_element(Stack.begin(),Stack.end());
        min[1]==1;
        return min[0];
    }
};

/**
 * 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();
 */

也可以用二级缓存,但是因为不能在输出最大值后判断二级缓存是否有效所以效果很受局限:

class MinStack {
public:
    /** initialize your data structure here. */
    vector<int> Stack;
    int min[2]={INT_MAX,0};
    int min2=INT_MAX;
    bool v2=true;
    MinStack() {
        
    }
    
    void push(int x) {
        if (x<min[0]){
            min2=min[0];
            min[0]=x;min[1]=1;}
        else if(x==min[0]){min[1]++;}
        if(min[1]<1){v2=false;}
        Stack.push_back(x);
    }
    
    void pop() {
        int i=Stack.back();
        Stack.pop_back();
        if(i==min[0]){min[1]--;}
        if(i==min2){v2=false;}
    }
    
    int top() {
        return Stack.back();
    }
    
    int getMin() {
        if(min[1]>0){return min[0];}
        if(v2){return min2;}
        min[0]=*min_element(Stack.begin(),Stack.end());
        min[1]==1;
        return min[0];
    }
};

/**
 * 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();
 */

这几个速度内存占用都差不多:

Success

Runtime: 28 ms, faster than 97.14% of C++ online submissions for Min Stack.

Memory Usage: 16.8 MB, less than 85.36% of C++ online submissions for Min Stack.

当然最优解决方法还是建立二叉堆,这里求最小值肯定是用小顶堆,但是写起来就比较麻烦不适合解题用就算了。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值