关于队列和栈的几道面试题

来源:互联网 发布:linux arp缓存查询 编辑:程序博客网 时间:2024/05/22 14:19

今天来说几道简单的栈和队列相关的几道面试题:


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

第一道题,我们需要分析,我想一般的思维肯定是想到,开辟一块空间,进行保存最小值,这种方法也是大家通常地一下就可以想到的。但是在这里会有一个问题,就是如果你的最小值在栈顶,当你pop了栈顶以后,下面的数据中最小的元素就会发生改变,这个时候你无法得到新的最小的元素了。

所以,我们给出一种解决思路:就是你需要有两个栈,一个保存数据,一个辅助作为保存最小值情况的栈。,然后当我们进行push的时候,如果辅助最小值的栈也是空的,那么就push,不是空的时候和最小值栈的栈顶进行比较,如果比它小,再进行压栈,否则,就不用push。在pop的时候,这个时候我们需要和栈顶比较,如果pop的数值和栈顶是一样大的话,那么久吧保存数据的栈和最小值的栈的栈顶都进行pop。

这里写图片描述

    #define _CRT_SECURE_NO_WARNINGS 1    #pragma once    #include<iostream>    #include<cstdlib>    #include<cassert>    #include<stack>    #include<vector>    using namespace std;    template<typename T>    class Stack    {    public:        void push(const T& d);        void pop();        T& min();    private:        stack<T>DataStack;        stack<T>MinStack;    };    template<typename T>    void Stack<T>::push(const T& d)    {        DataStack.push(d);        if (MinStack.empty() || d <= MinStack.top())        {            MinStack.push(d);        }    }    template<typename T>    void Stack<T>::pop()    {        assert(!DataStack.empty());        if (DataStack.top() == MinStack.top())        {            DataStack.pop();            MinStack.pop();        }        DataStack.pop();    }    template<typename T>    T& Stack<T>::min()    {        return MinStack.top();    }

2 . 使用两个栈实现一个队列

对于这个问题的分析,我们可以转换为两个栈之间的来回循环倒的一个问题。
在这,我们应该清楚,两个数据结构的数据特性,一个是先进后出,一个是后进先出,所以,我们在这里可以这样分析:
当我们入队操作的时候,对第一个栈进行压栈,如果我们想要pop的时候,这个时候其实是要pop的是第一个栈的栈底元素,所以这个时候我们把第一个栈栈顶元素push进入第二个栈,然后pop,这样依次到第一个栈空。然后我们再pop第二个栈顶元素的top,这样就是实现了出队。

这里写图片描述

    #pragma once    #include<iostream>    #include<cstdlib>    #include<cassert>    #include<stack>    using namespace std;    template<typename T>    class Queue    {    public:        void push(const T& d);        void pop();        size_t size();        bool empty();        T& front();        T& back();    private:        stack<T > s1;        stack<T > s2;    };    template<typename T>    void Queue<T>::push(const T& d)    {        s1.push(d);    }    template<typename T>    void Queue<T>::pop()    {        assert((!s1.empty() )||(! s2.empty()));        if (s2.empty())        {            while (!s1.empty())            {                s2.push(s1.top());                s1.pop();            }        }        s2.pop();    }    template<typename T>    size_t Queue<T>::size()    {        return s1.size() + s2.size();    }    template<typename T>    bool Queue<T>::empty()    {        return s1.empty()&&s2.empty();    }    template<typename T>    T& Queue<T>::front()    {        assert((!s1.empty()) || (!s2.empty()));        if (s2.empty())        {            while (!s1.empty())            {                s2.push(s1.top());                s1.pop();            }        }        return s2.top();    }    template<typename T>    T& Queue<T>::back()    {        assert((!s1.empty()) || (!s2.empty()));        if (s1.empty())        {            while (!s2.empty())            {                s1.push(s2.top());                s2.pop();            }        }        return s1.top();    }

3 . 使用两个队列实现一个栈

这道题是利用两个队列实现一个栈,和上面的那道题的方法是类似的,依然是通过调转实现数据特性就好了。让数据在两个队列当中进行流动,首先我们要确保数据必须只在一个栈中,push的时候对有元素的栈进行push。然后当我们pop的时候我们把一个队列中除了队尾的元素都push进第二个队列,最后把队尾的元素pop出去就好了,这样就可以实现一个栈。
这里写图片描述

#pragma once#include<iostream>#include<cstdlib>#include<cassert>#include<queue>using namespace std;template<typename T>class Stack{public:    void push(const T & d);    void pop();    size_t size();    bool empty();    T& top();private:    queue<T> q1;    queue<T> q2;};template<typename T>void Stack<T>::push(const T& d){    if (q2.empty()&&q2.empty())    {        q1.push(d);    }    else if (!q1.empty())    {        q2.push(d);    }    else        q1.push(d);}template <typename T>void Stack<T>::pop(){    assert(!q1.empty() || !q2.empty());    if (!q1.empty())    {        while (q1.size()>1)        {            q2.push(q1.front());            q1.pop();        }        q1.pop();    }    else    {        while (q2.size()>1)        {            q1.push(q2.front());            q2.pop();        }        q2.pop();    }}template <typename T>bool Stack<T>::empty(){    return q1.empty() && q2.empty();}template <typename T>size_t Stack<T>::size(){    return q1.size() + q2.size();}template <typename T>T& Stack<T>::top()  {    assert(!q1.empty() || !q2.empty());    if (!q1.empty())    {        return q1.back();    }    else    {        return q2.back();    }}

4 . 元素出栈、入栈顺序的合法性。如入栈的序列(1 , 2 , 3 , 4 , 5 ),出栈序列为(4 , 5 , 3 , 2 , 1 )

这道题的思路也很简单,就是你所给定的两个序列数组,一个入栈序列,一个出栈序列。入栈序列比如说是(1,2,3,4,5);出栈序列比如说是(4,5,3,2,1);我们就首先入栈序列第一个元素入栈,这个时候让一个指针指向出栈序列第一个元素,如果出入栈以后,栈顶元素和指针所指的元素相等,那么就让栈顶元素出栈,让指针++,最后判定栈是否为空就好了,如果为空,就说明是合法的,如果不为空,就不合法。

//判断元素出栈、入栈顺序的合法性。//如:入栈的序列(1,2,3,4,5)//出栈序列为(4,5,3,2,1),是合法序列//入栈序列(1,2,3,4,5),//出栈序列为(1,5,3,2,4)是不合法序列#pragma once#include<iostream>#include<cstdlib>#include<cassert>#include<stack>using namespace std;int j = 0;bool JudgeStackSeq(int *InArr, int *OutArr, size_t sz){    stack<int > s;    int j = 0;    int pos=0;    for (size_t i = 0; i < sz; i++)    {        s.push(InArr[i]);        while (!s.empty()&&s.top()==OutArr[j])        {            s.pop();            j++;        }    }    return s.empty();}

5 . 一个数组实现两个栈

最后是一个数组实现两个栈这个问题,这个问题我们可以采用三种思路来实现:

  • 采用奇偶栈
  • 采用中间向两头的栈
  • 采用两边向中间的栈
    这里写图片描述

上面两种都会存在空间利用率较低的问题,比如有一个栈数据很多,一个栈数据非常小,这个时候第三种方案是最好一些的。

#pragma once #include<iostream>#include<cassert>#include<cstdlib>using namespace std;template<typename T>class Stack{public:    Stack()        : _array(0)        , _sz1(0)        , _sz2(0)        , _capacity(0)    {    }    ~Stack()    {        if (_array != NULL)        {            delete[] _array;        }    }    void push1(const T& d)    {        CheckCapacity();        _array[_sz1] = d;        _sz1++;    }    void pop1()    {        assert(_sz1 > 0);        _sz1--;    }    bool empty1()    {        return _sz1 == 0;    }    void push2(const T& d)    {        CheckCapacity();        _array[_sz2] = d;        _sz2--;    }    void pop2()    {        assert(_sz2 < _capacity - 1);        _sz2++;    }    bool empty2()    {        return _sz2 == _capacity - 1;    }    size_t size1()    {        return _sz1;    }    size_t size2()    {        return _capacity - 1 - _sz2;    }    T& top1()    {        assert(_sz1 > 0);        return _array[_sz1 - 1];    }    T& top2()    {        assert(_sz2 != 0 || _sz2 < _capacity - 1);        return _array[_sz2 + 1];    }    void CheckCapacity()    {        if (_sz1 ==_sz2)        {            size_t NewCapacity = 2 * _capacity+2 ;            T* tmp = new T[NewCapacity];            for (size_t i = 0; i < _sz1; ++i)            {                tmp[i] = _array[i];            }            size_t j(0);            for (j = NewCapacity - 1; j<NewCapacity-1&&j>NewCapacity - _sz2; --j)            {                tmp[j] = _array[_capacity];            }            _sz2 = NewCapacity - (_capacity - _sz2);            _capacity = NewCapacity;            _array = tmp;        }    }protected:    T* _array;    size_t _sz1;    size_t _sz2;    size_t _capacity;};
0 0
原创粉丝点击