栈和队列的经典面试题(一)

来源:互联网 发布:java io读取文件 编辑:程序博客网 时间:2024/06/05 10:32
一、实现一个栈,要求实现Push(入栈)、Pop(出栈)、Min(返回最小值的操作)的时间复杂度为O(1)。 

分析:
    思路1:利用两个栈,第二个栈的栈顶只放当前原生栈的最小值,Pop和Push时两个栈都进行,Min时只有第二个栈返回其栈顶值。
    eg1——以入栈 5 3 6 7 8 0 为例,其入栈、求最小值、出栈的过程如下图:

此思路在本例题下可行,但如果换个例子,要求入栈 5 3 6 3 3 0 的话就会出状况,这个时候,需要进行改进。
    改进1:如果原生栈中的元素不重复时,第二个栈中不出现重复数字;若原生栈中的元素出现重复时,第二个栈中同样引入该重复数字。Push时第二个栈只压入截至目前的最小值和原生栈中重复的数,Pop时第二个栈只在等于原生栈中值时才出,Min时只有第二个栈返回其栈顶值。入栈、求最小值、出栈的过程如下图:

但这时仍然存在问题,即当原生栈需要压入的数据有大量重复的时候,思路二的方法的效率就会显得很低。这时仍需要进行改进。
    改进2:使用引用计数,对第二个栈中的每个数配一个引用计数,当引用计数为0时再Pop。此方法为最优方法。
实现:
思路1实现:
#include <iostream>#include <stack>using namespace std;template <class T>class MinStack{public:       void Push(const T& x)       {              _st.push(x);              if ((_minst.empty()) || (x < _minst.top()))              {                     _minst.push(x);     //minst为空时直接压栈,不为空时需要判断是否为当前最小值              }              else              {                     _minst.push(_minst.top());  //保持压入最小值              }       }       void Pop()       {              _st.pop();              _minst.pop();       }       void Min()       {              /*return _minst.top();*/              cout << "min= " << _minst.top() << endl;       }       void Print()       {                     while (!_st.empty())                     {                           cout << _st.top() << " ";                           _st.pop();                     }                     cout << endl;       }protected:       stack<T> _st;       stack<T> _minst;};int main(){       MinStack<int> s;       s.Push(3);       s.Push(2);       s.Push(6);       s.Push(5);       s.Push(1);       s.Push(7);       /*s.Min();       s.Print();*/       s.Pop();       s.Pop();       s.Min();       s.Print();       system("pause");       return 0;}
改进1实现(只需更改Push和Pop):
void Push(const T& x)       {              _st.push(x);              if ((_minst.empty()) || (x <= _minst.top()))              {                     _minst.push(x);     //minst为空时直接压栈,不为空时需要判断是否为最小值或重复值              }       }       void Pop()       {              if (_st.top() == _minst.top())              {                     _minst.pop();              }              _st.pop();       }     
改进2的实现:
template <class T>class MinStack{public:       struct ValueRef    //定义一个内部类作第二个栈       {              T _value;              size_t _ref;    //计数              ValueRef()   //构造 初始化_ref                     :_ref(0)              {}       };protected:       stack<T> _st;       stack<ValueRef> _minst;};
添加内部类,其他运算据此进行。

二、使用两个栈实现一个队列。

分析:
有两个栈s1和s2,s1负责入队,压栈即可。出队时,若s2为空,将s1中元素导入s2中,若s2不为空,由s2出栈来完成出队。

实现:
#include <iostream>#include <stack>using namespace std;template <typename T>class CQueue{public:       CQueue(void)       {}       ~CQueue(void)       {}       void appendTail(const T& node);       T deleteHead();private:       stack<T> stack1;       stack<T> stack2;};template<class T>void CQueue<T>::appendTail(const T& node)//在队列尾部添加数据{       stack1.push(node);}template<class T>T CQueue<T>::deleteHead(){       T tmp = 0;       if (stack2.empty()) //若栈2为空       {              while (!stack1.empty())              {                     tmp = stack1.top();                     stack2.push(tmp);                     stack1.pop();              }       }       tmp = stack2.top();       stack2.pop();       return tmp;}void Test(){       CQueue<int> q1;       q1.appendTail(1);       q1.appendTail(2);       q1.appendTail(3);       q1.appendTail(4);       q1.deleteHead();       q1.appendTail(5);       q1.appendTail(6);       q1.appendTail(7);}int main(){       Test();       system("pause");       return 0;} 

三、使用两个队列实现一个栈

分析:
进栈:把元素push进非空的队列,如果两者都是空的,则随意。 
出栈:把非空队列里面的前n-1个元素push到空队列里面,再把最后一个元素拿出来即可。 
循环以上步骤,即可得到实现目的。
实现:
#include "queue"#include "iostream"using namespace std;template <typename T>class Stack {public:       Stack() {              count = 0;       }       ~Stack() {}       void push(const T & data) {              if (!q2.empty()) {                     q2.push(data);              }              else {                     q1.push(data);              }              count++;       }       T pop() {              T temp;              if (!q1.empty()) {                     for (int i = 0; i < count - 1; ++i) {                           q2.push(q1.front());                           q1.pop();                     }                     temp = q1.front();                     q1.pop();                     count--;                     return temp;              }              else if (!q2.empty()) {                     for (int i = 0; i < count - 1; ++i) {                           q1.push(q2.front());                           q2.pop();                     }                     temp = q2.front();                     q2.pop();                     count--;                     return temp;              }       }       T top() {              T temp;              if (!q1.empty()) {                     for (int i = 0; i < count - 1; ++i) {                           q2.push(q1.front());                           q1.pop();                     }                     temp = q1.front();                     q2.push(temp);                     q1.pop();                     return temp;              }              else if (!q2.empty()) {                     for (int i = 0; i < count - 1; ++i) {                           q1.push(q2.front());                           q2.pop();                     }                     temp = q2.front();                     q1.push(temp);                     q2.pop();                     return temp;              }       }       int size() const { return count; }       bool empty() {              return count == 0;       }private:       queue<T> q1;       queue<T> q2;       int count;};template <typename T>           //注意非模板类的成员函数的模板姿势int print(Stack<T> s) {       while (!s.empty()) {              cout << s.pop() << " ";       }       cout << endl;}


原创粉丝点击