数据结构和算法:最小栈

内卷之源:

https://leetcode-cn.com/problems/min-stack/

题目描述:

 * 设计一个支持 push、pop 和 top 操作,并能在 常数时间 内检索到最小元素的栈。
 * 说明:
      -2^31 <= val <= 2^31 - 1   //int型取值范围
      pop、top 和 getMin 操作总是在 非空栈 上调用
      push、pop、top 和 getMin 最多被调用 3 * 10^4 次

测试用例:

push(-2) —— 最先入栈的元素在栈底
push(0)
push(-3) —— 最后入栈的元素在栈顶
getMin() —— 此时栈中有三个元素,最小元素是 -3
pop()      —— 删除栈顶元素 -3,此时栈中只有两个元素,最小元素 -2
top()       —— 返回栈顶元素 0
getMin() —— 此时栈中只有两个元素,最小元素是 -2

思路分析:

 *   对于 push、pop 和 top 操作,最简单的方式就是借助C++标准库的stack容器,均为常数时间复杂度。
 *   获取栈中最小元素的办法一般是对栈中所有元素进行一次遍历,显然不符合在“常数时间”内检索到最小元素这一要求。
 *   常见的两种方法:
        法一:创建两个栈 数据栈 + 辅助栈,数据栈用于响应外部栈操作请求。
                   每次push操作时,若该元素不大于辅助栈栈顶元素(等于条件用于解决在连续push进数据栈的元素都不小于辅助栈栈顶元素,且有多个元素等于辅助栈栈顶元素的情况),将其同步添加到辅助栈,因此最小元素始终在辅助栈的栈顶。
                   每次top操作时,辅助栈栈顶元素若与数据栈栈顶元素相同,也同步删除辅助栈栈顶元素。
                   每次获取栈最小元素,直接返回辅助栈栈顶元素。若辅助栈为空,则数据栈必为空。
        法二:创建单个数据栈,每个栈元素包含两个值,一个是当前位置push进的数,另一个则是当前栈中最小的数。(法一的优化版)
                   将两个value视为一个单元的场合在C++中常用工具pair<>
 *   用C实现时,使用单链表构建栈即可。

编程实现(C++):

/*
 ************************************************************
 * @author    SLF
 * @version	  V1.0.0
 * @date      29-May-2021
 ************************************************************
 */

#include <iostream>
#include <vector>
#include <utility>
#include <stack>

using namespace::std;

class MinStack {
public:
    MinStack()
    {//stack默认基于deque实现
        ;
    }

    ~MinStack() {}
    
    void push(const int val)
    {
        int min_val = val;

        if(!datastack.empty())
        {
            min_val = datastack.top().second;
            if(min_val > val)
            {
                min_val = val;
            }
        }

        datastack.push({val, min_val});
    }
    
    void pop()
    {
        if(datastack.empty())
        {
            return;
        }

        datastack.pop();
    }
    
    int top() const
    {
        if(datastack.empty())
        {
            return INT32_MAX;
        }

        return datastack.top().first;
    }
    
    int getMin() const
    {
        if(datastack.empty())
        {
            return INT32_MAX;
        }

        return datastack.top().second;
    }

private:
    stack<pair<int,int>> datastack;
};

class MinStack_Aux {
public:
    MinStack_Aux()
    {//stack默认基于deque实现
        ;
    }

    ~MinStack_Aux() {}
    
    void push(const int val)
    {
        if(auxstack.empty()) //第一次
        {
            auxstack.push(val);
        }
        else
        {
            if(auxstack.top() >= val)
            {
                auxstack.push(val);
            }
        }

        datastack.push(val);
    }
    
    void pop()
    {
        if(auxstack.empty()) //数据栈和辅助栈不会出现一个为空,而另一个不为空的情况
        {
            return;
        }

        if(auxstack.top() == datastack.top())
        {
            auxstack.pop();
        }

        datastack.pop();
    }
    
    int top() const
    {
        if(datastack.empty())
        {
            return __INT32_MAX__;
        }

        return datastack.top();
    }
    
    int getMin() const
    {
        if(auxstack.empty())
        {
            return __INT32_MAX__;
        }

        return auxstack.top();
    }

private:
    stack<int> datastack;
    stack<int> auxstack;
};

int main(void)
{
    MinStack stk;
    //MinStack_Aux stk;
    const vector<vector<int>> test_data = {{-2, 0, -3}, {-2, 0, -2, -3}, {-2, 0, -3, -2}};

    const int n = test_data.size();
    for(int i = 0; n > i; ++i)
    {
        cout << "第" << i << "组" << endl;
        for(const auto d : test_data[i])
        {
            stk.push(d);
        }

        const int m = test_data[i].size() + 1; //题设中已假定 pop、top 和 getMin 操作总是在 非空栈 上调用
        for(int j = 0; m > j; ++j)
        {
            cout << "TOP: " << stk.top() << endl;
            cout << "MIN: " << stk.getMin() << endl << endl;
            stk.pop();
        }
    }

    return 0;
}

  

郑重提示:①解题思路非最优,覆盖条件可能不全,仅供练习参考。

                  ②若有更佳思路或疑问,可在评论区留言相互讨论,不亦乐乎。

                  ③本文不允许转载,若认可本文,可点赞收藏关注。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值