实现最小栈

题目要求

实现一个栈,要求实现Push(出栈)、Pop(入栈)、Min(返回最小值的操作)的时间复杂度为O(1)

首先针对这道题有多重解决方案。
1、定义两个栈,一个正常栈,另一个栈的栈顶始终保存整个栈内的最小值。

思路如下:

  1. 无论Push什么数据,正常栈肯定直接Push进去。
  2. 而当新Push的数据大于最小栈的栈顶时,最小栈将自己的栈顶再次Push一遍。
  3. 而当新Push的数据小于最小栈的栈顶时,意思是该数据现在是整个栈中的最小值,则将该值也直接Push进最小栈

这里写图片描述

这种思路的Pop和就很简单了,每次Pop时,将两个栈的栈顶都Pop出去就好了,求Min的话,直接返回最小栈的栈顶。

基于这种思路,写出如下代码:

template<class T>
class MinStack
{
public:
    void Push2(const T value)
    {
        if (_s.empty() || _min.top() > value)
        {
            _s.push(value);
            _min.push(value);
        }
        else
        {
            _s.push(value);
            _min.push(_min.top());
        }

    }

    void Pop()
    {
        _s.pop();
        _min.pop();
    }

    T Min()
    {
        return _min.top();
    }
private:
    stack<T> _s;
    stack<T> _min;
};

2、在第一种的思路中,最小栈将当前最小的值重复存放了好多份,可不可以只存一份呢?加上引用计数!
如果直接只存一份的话,会出现下面这种情况。
每次Pop时,如果待Pop的值大于最小栈中的栈顶数据,就只Pop正常栈,但是如果栈中有两个相同元素呢?

这里写图片描述

template <class T>
class MinStack
{
public:
    void Push(const T value)
    {
        if (_s.empty() || _min.top().first > value)
        {
            _s.push(value);
            _min.push(make_pair(value, 1));
        }
        else if (_min.top().first == value)
        {
            _s.push(value);
            _min.top().second += 1;
        }
        else
        {
            _s.push(value);
        }
    }

    void Pop()
    {
        T top = _s.top();
        if (top == _min.top().first)
        {
            if (_min.top().second > 1)
                --_min.top().second;
            else
                _min.pop();

            _s.pop();
        }
        else
        {
            _s.pop();
        }
    }

    int Min()
    {
        return _min.top().first;
    }
private:
    stack<int> _s;
    stack<pair<int, int>> _min;
};

3、使用一个栈,每次Push两个值,一个正常值,一个是最小值,什么意思呢?

template <class T>
class MinStack
{
public:
    void Push(const T value)
    {
        if (_s.empty() || _s.top() > value)
        {
            _s.push(value);
            _s.push(value);
        }
        else
        {
            T top = _s.top();
            _s.push(value);
            _s.push(top);
        }
    }

    void Pop()
    {
        _s.pop();
        _s.pop();
    }

    int Min()
    {
        return _s.top();
    }
private:
    stack<int> _s;
};

4、基于第三种方法,可以每次Push一个键值对,一个保存正常值,一个保存最小值,和第三种思想是一样的。

template <class T>
class MinStack
{
public:
    void Push(const T& value)
    {
        if (_s.empty() || _s.top().second > value)
        {

            _s.push(make_pair(value, value));
        }
        else
        {
            _s.push(make_pair(value, _s.top().second));
        }
    }

    void Pop()
    {
        _s.pop();
    }

    T Min()
    {
        return _s.top().second;
    }
private:
    stack<pair<int, int>> _s;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值