栈和队列面试题1【菜鸟学习日记】

开篇点题,今天做了几道栈和队列的题,
在此,记录分享

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

来分析一下,
思路1:我们可以底层用两个栈来实现
先建个类,写个框架,实现3个接口

class MinSt
{
public:
    void Push(const int& x)
    {...}

    void Pop()
    {...}

    int Min()
    {...}
protected:
    stack<int> _st;
    stack<int> _minst;
};

然后我们再来分析一下如何写,分析一下过程
这里写图片描述

虽然我们底层是用两个栈实现的,但外面看起来要像一个栈,那么我们这两个栈要保持一致,同进同出
这里进栈出栈时,_st栈不用特殊考虑,但_minst我们是用它记录最小值的所以要特殊考虑
我们可以从上图看到,_minst入栈的要求是比当前栈顶的数小或者等于才能入栈,否则将当前栈顶再入栈
void Push(const int& x)
    {
        _st.push(x);
        if (_minst.size() == 0||x<_minst.top())
        {
            _minst.push(x);
        }
        else
        {
            _minst.push(_minst.top());
        }
    }
此时我们_minst的栈顶永远是最小值

出栈时,只要考虑不为空即可

void Pop()
    {
        if (!_st.empty() && !_minst.empty())
        {
            _st.pop();
            _minst.pop();
        }
    }
返回最小值就Pop出_minst栈顶
    int Min()
    {
        if (!_minst.empty())
        {
            return _minst.top();
        }
    }

测试一下

void test1()
{
    MinSt s;
    s.Push(5);
    s.Push(3);
    s.Push(6);
    s.Push(1);
    s.Push(2);

    s.Pop();
    s.Pop();

    cout << s.Min() << endl;

}
这个写法还可以优化,_minst中重复入栈3,我们还可以用其他方法优化,后面再补充

2、用两个栈实现一个队列

我们先来画图分析一下
这里写图片描述

class TwoStackOneQueue
{
public:
      ...
private:
    stack<int> PushStack;
    stack<int> PopStack;
};
先创建两个栈,一个用来入,一个用来出
我们大概先说一下思路
入栈1,2,3
当要Pop时,将1,2,3导入进PopStack,这时的栈顶,就是我们应该要Pop的正确数了
然后我们再入栈时应该入PushStack

首先我们先来实现Push()接口,这个接口我们不用特别考虑什么,想清楚入栈都入PushStack

void Push(const int&x)
    {
        //入时永远入PushStack栈
        PushStack.push(x);
    }
然后就是出栈

我们每次出PopStack即可,如果为空了,就将PushStack倒过去,再出就好

下面是全部代码
class TwoStackOneQueue
{
public:
    void Push(const int&x)
    {
        //入时永远入PushStack栈
        PushStack.push(x);
    }

    void Pop()
    {
        if (PopStack.empty())
        {
            PutPop();
        }
        PopStack.pop();
    }

    int& Front()
    {
        if (PopStack.empty())
        {
            PutPop();
        }
        return PopStack.top();
    }

    bool Empty()
    {
        return PushStack.empty() && PopStack.empty();
    }

    size_t Size()
    {
        return PushStack.size() + PopStack.size();
    }
private:
    void PutPop()
    {
        while (!PushStack.empty())
        {
            PopStack.push(PushStack.top());
            PushStack.pop();
        }
    }
private:
    stack<int> PushStack;
    stack<int> PopStack;
};
void test2()
{
    TwoStackOneQueue q;
    q.Push(1);
    q.Push(2);
    q.Push(3);

    q.Pop();
    cout<<q.Front()<<endl;//2
    q.Pop();
    cout << q.Front() << endl;//3

    q.Push(4);
    q.Pop();
    cout << q.Front() << endl;//4
}

这里写图片描述


3、用两个队列实现一个栈

这里写图片描述

入队列1,2,3,4
可是我们现在要出4,所以我们可以将1,2,3全放到另一个队列中去,就可以出4了
我们如数据的时候都入不为空有数据的那个,这样我们才能就一个在出的时候将前面数据移过去,出队列
要知道哪个空队列,写个函数就好了
还有就是移数据也可以单独写个函数,方便后面调用,并最好都设为私有,外面看不到,这样只能看到那些栈有的接口,更好一些
private:
    void PutEmpty()
    {
        QEmpty();
        while (nonemptyq->size() > 1)
        {
            emptyq->push(nonemptyq->front());
            nonemptyq->pop();
        }
    }
    void QEmpty()
    {
        if (_q2.empty())
        {
            swap(emptyq, nonemptyq);
        }
    }

其它的也就没什么了,不说了,上全部代码

class TwoQueueOneStack
{
public:
    void Push(const int&x)
    {
        //入时入非空的队列
        QEmpty();
        nonemptyq->push(x);
    }

    void Pop()
    {
        PutEmpty();
        nonemptyq->pop();
    }

    int& Top()
    {
        QEmpty();
        return nonemptyq->back();
    }
    bool Empty()
    {
        return _q1.empty() && _q2.empty();
    }

    size_t Size()
    {
        return _q1.size() + _q2.size();
    }

private:
    void PutEmpty()//移数据
    {
        QEmpty();
        while (nonemptyq->size() > 1)
        {
            emptyq->push(nonemptyq->front());
            nonemptyq->pop();
        }
    }
    void QEmpty()
    {
        if (_q2.empty())
        {
            swap(emptyq, nonemptyq);
        }
    }
private:
    queue<int> _q1;
    queue<int> _q2;

    queue<int>* emptyq = &_q1;
    queue<int>* nonemptyq = &_q2;
};

void test3()
{
    TwoQueueOneStack s;

    s.Push(1);
    s.Push(2);
    s.Push(3);
    s.Push(4);

    s.Pop();
    cout << s.Top()<<endl;//3

    s.Push(5);
    cout << s.Top() << endl;//5

}

这里写图片描述

以上,今天总结完毕,剩下的以后再写吧!

———-【菜鸟日记】by 小宣子

  • 0
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值