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

来源:互联网 发布:mac有必要分区吗 编辑:程序博客网 时间:2024/06/06 08:38

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

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 小宣子