旭说数据结构之栈的小题目

1.定义栈的数据结构,要求添加一个min()函数,能够得到栈的最小元素。要求函数min(),push(),及pop()函数的时间复杂度都是O(1).

如果用上一篇文章中栈的实现方式“旭说数据结构之栈”,push和pop的时间复杂度可以是O(1),但是要想获得栈中的最小元素,需要遍历存储元素的数组,时间复杂度为O(n)。
这是得考虑变换栈的数据结构。

思考1:
如果说我们给栈这个类添加一个成员变量min,用来记录栈中的最小值。
1. 假设第一次push进入元素1时,设置min=1;
2. 再次想让2进栈时,先把2和min进行比较,发现2没有min小,min的值不用改变,然后再把2进栈;
3. 想让3进栈时,重复2中的步骤

这时栈中的元素为1、2、3,min的值为1,当我们想要知道栈中的最小值时,可以直接返回min的值,时间复杂度为O(1)。再多考虑一点,如果我们进行一次出栈操作,发现栈顶元素3比min大,不用改变min的值。这时栈中元素为1、2,min=1,
似乎依旧是正确的。我们再多考虑一点,这是我们入栈0,由于0是小于的min,所以设置min=0,这时栈中元素为1、2、0,min为0,这时我们就能发现问题了,把0出栈,0和min的值是相同的,我们不知道该把min设置为何值。这个思路是不对的。

思考2:
首先思考一下为什么思考1的思路有问题:
状态A:(1、2、3 min=1)
把0入栈得到状态B
状态B:(1、2、3、0,min= 0),
把栈顶元素0出栈后没法知道0入栈前的状态A中的最小值为多少,因为得到min=0的过程没有之前的min=1和入栈元素0的参与,也就没法恢复状态A。
这是如果想知道0出栈后的最小值就得遍历数组,这是时间复杂度就不是O(1)了。

所以我们要把入栈元素值入栈前的min,以及入栈后的min建立联系。
发现:什么时候入栈后的min才会变化呢,只有当小于min的值入栈时。
当小于min的值入栈时,入栈后的min值应该等于入栈元素的本来值,于是我们可以不把本来值存入栈顶,而是把入栈前的min的信息记录到栈顶,即把入栈元素的本来值-入栈前的min(这个差值是小于0的)存入栈顶。这样便把三者的关系建立了。想要获得栈顶元素,只需要把入栈后的min返回出去,然后min - 栈顶值 即可或得入栈前的min。
当大于min的值入栈时,把入栈元素的本来值-min(这个值是大于0的)的差值存入栈顶,入栈后的min的值等于入栈前的min的值。当栈顶元素出栈时,由于知道栈顶存的是差值,且该差值是大于0的,所以知道min的值不需要改变。
利用这个思路就可以实现题目中的要求了。
具体的实现明天再补上。
补上实现代码:

#include <cassert>
template<typename DataType>class StackWithMin
{
public:
    StackWithMin(int capacity = 10)
    {
        _capacity = capacity;
        _datas = new DataType[capacity];
        _top = -1;
    }
    bool push(DataType data)
    {
        if (_top + 1 == _capacity)return false;//栈满,返回false

        if (_top == -1)//如果开始栈为空的话,设置_min为第一次push的值
        {
            _min = data;
            _top++;
            _datas[_top] = data - _min;
        }else{//在栈中有元素时push
            if (data >= _min)//如果要push进栈的值比此时的_min大,
            {
                _top++;
                _datas[_top] = data - _min;
            }else{//如果要push进栈的值比此时的_min小,
                _top++;
                _datas[_top] = data - _min;
                _min = data;
            }
        }   
        return true;
    }
    DataType pop()
    {
        /*if (_top == -1)exit(-1);*/
        assert(_top!= -1);
        if (_datas[_top]<0)//如果栈顶的值小于0,说明栈顶元素的本来值就是当前的最小值_min,出栈后_min应该改变
        {
            DataType temp = _min;
            _min = _min - _datas[_top--];
            return temp;
        }else{//如果栈顶的值大于等于0,说明栈顶元素的本来值要大于当前的_min,本来值应该等于当前的_min+栈顶值.
            return _min + _datas[_top--];
        }


    }
    DataType getmin()
    {
        if (_top == -1)
        {
            exit(-1);
        }
        return _min;
    }

private:
    DataType* _datas;
    int _capacity;
    int _top;
    DataType _min;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值