剑指Offer21包含min函数的栈

题目:

定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的函数,在该栈中,调用min,push,pop的时间复杂度都是O(1)。

分析:

如果想让其时间复杂都为1的话,那么就需要记录栈中的最小值,如果我们进行比较再入栈,那么push的时间复杂度就不只是1了,所以这种想法是不行的,如果我们记录一个最小值虽然能满足,但是当这个最小值被弹出之后就不能马上找到剩下元素的最小值了,所以我需要一个容器来记录每一个最小值。

那么我们可以再来一个栈,这个栈中定义最小元素,如果一个数字进入1栈,那么我们就比较一下,如果这个数比2栈中的数字小就进入2栈,如果比2栈中的数大就把2栈当前的数字再压入2栈,这样就能保证2栈栈顶的元素是1栈中最小的。当1栈弹出数字之后,2栈也相应的往外弹出。无论怎么弹栈和进栈都能保证2栈中的栈顶元素是1栈中最小的。

思路理清了代码就很简单了

void PushStack(int value)
{
    t1.push(value);
    if(t2.empty())
        t2.push(value);
    else
    {
        int min = t2.top();
        if(min>value)
            t2.push(value);
        else
            t2.push(min);
    }
}
int PopStack()
{
    int result = -1;

    if(!t1.empty())
    {

        t1.pop();
        result = t2.top();
        t2.pop();
    }
    if(result == -1)
        cout<<"栈空了"<<endl;
    return result;
}
void FindMin()
{
    if(!t2.empty())
        cout<<t2.top()<<endl;
    else
        cout<<"栈空了,找不到最小元素"<<endl;
}

思维扩展:

如果说这个题目中不是栈而是队列呢?

我们之前做过两个栈模拟队列,两个队列模拟栈,然后再加上我们刚刚做了上面的分析,是不是能把这个两个点结合起来,就能解决问题呢?

我们可以试一下。

首先是用两个栈来模拟队列,如果我们需要求最小值,那么还需要两个栈来存储刚才的两个栈。这样我们总共有了四个栈。


当队列里进入2 1 3后,我们来用栈模拟,此时A栈中一次进入2 1  3 ,A的最小栈中的一次存入2 1 1 ,当2从队列中弹出之后,那么就要从A栈向B栈压入。此时B栈为3 1 2,将2从B栈中弹出,每一次都是从B栈弹出来模拟出队列,进队列是从A栈进入。只有当B栈空了才从A栈弹入B栈中,最小值是比较两个栈顶元素谁最小。

下面是代码,写的挺乱,并且还有好多都是直接粘贴的,没有做成函数,凑合着看吧

stack<int> ta,tam,tb,tbm;
void PushQueue(int value)
{
    ta.push(value);
    if(tam.empty())
        tam.push(value);
    else
    {
        int min = tam.top();
        if(min > value)
            tam.push(value);
        else
            tam.push(min);
    }
}
void PopQueue()
{
    if(tb.empty())
    {
        while(!ta.empty())
        {
            int value = ta.top();
            tb.push(value);
            if(tbm.empty())
                tbm.push(value);
            else
            {
                int min = tbm.top();
                if(min > value)
                    tbm.push(value);
                else
                    tbm.push(min);
            }
        }
    }
    if(tb.empty())
    {
        cout<<"队列已空,不能弹出元素"<<endl;
        return ;
    }
    tb.pop();
    tbm.pop();

}
void FindMin()
{
     if(tb.empty())
    {
        while(!ta.empty())
        {
            int value = ta.top();
            tb.push(value);
            if(tbm.empty())
                tbm.push(value);
            else
            {
                int min = tbm.top();
                if(min > value)
                    tbm.push(value);
                else
                    tbm.push(min);
            }
            ta.pop();
        }
    }

    if(tam.empty() && tbm.empty())
    {
        cout<<"队列中没有元素"<<endl;
        return ;
    }

    if(tam.empty())
        cout<< tbm.top()<<endl;
    else
    {
        int mina = tam.top();
        int minb = tbm.top();
        int min = mina < minb ? mina : minb ;

        cout<< min <<endl;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值