题目描述:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
实现 MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
说明:
- 你只能使用标准的栈操作 —— 也就是只有
push to top
,peek/pop from top
,size
, 和is empty
操作是合法的。 - 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
进阶:
- 你能否实现每个操作均摊时间复杂度为
O(1)
的队列?换句话说,执行n
个操作的总时间复杂度为O(n)
,即使其中一个操作可能花费较长时间。
方法一:
class MyQueue {
public:
stack<int> sta;
/** Initialize your data structure here. */
MyQueue() {
}
/** Push element x to the back of queue. */
void push(int x) {
sta.push(x);
}
/** Removes the element from in front of queue and returns that element. */
int pop() {
stack<int> newsta;
while (!sta.empty())
{
int a = sta.top();
sta.pop();
newsta.push(a);
}
int b = newsta.top();
newsta.pop();
while (!newsta.empty())
{
int a = newsta.top();
newsta.pop();
sta.push(a);
}
return b;
}
/** Get the front element. */
int peek() {
stack<int> newsta;
while (!sta.empty())
{
int a = sta.top();
sta.pop();
newsta.push(a);
}
int b = newsta.top();
while (!newsta.empty())
{
int a = newsta.top();
newsta.pop();
sta.push(a);
}
return b;
}
/** Returns whether the queue is empty. */
bool empty() {
return sta.empty();
}
};
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue* obj = new MyQueue();
* obj->push(x);
* int param_2 = obj->pop();
* int param_3 = obj->peek();
* bool param_4 = obj->empty();
*/
关于pop()和peek()函数,实在想不出什么好方法,只能这样暴力解了。
方法二:
class MyQueue {
public:
stack<int> sta1; //输入栈,入队时就把元素压入这个栈中
stack<int> sta2; //输出栈,出队时就从这个栈中弹出元素
MyQueue() {
}
void push(int x) {
sta1.push(x);
}
int pop() {
if (sta2.empty())
{
while (!sta1.empty())
{
sta2.push(sta1.top());
sta1.pop();
}
}
int a = sta2.top();
sta2.pop();
return a;
}
int peek() {
if (sta2.empty())
{
while (!sta1.empty())
{
sta2.push(sta1.top());
sta1.pop();
}
}
return sta2.top();
}
bool empty() {
return sta1.empty() && sta2.empty();
}
};
一个很巧妙地方法,合理运用两个栈,用sta1来存储入队的元素,用sta2来存储即将出队的元素。
参考下图:
图中,一开始sta1中push进了1,2,3, 然后执行一次pop()操作之后,sta1中的元素放入sta2中并弹出队首元素1。
当要进行 pop() 或 peek() 操作时:
①若sta2不为空,则sta2中的元素就是队列前面的元素,sta2的栈顶元素就是队列的队首元素
②若sta2为空,则需要再次将sta1中的元素压入sta2中。注意!当sta2不为空的时候,还不能将sta1中的元素压入sta2中,例如上图中若把sta1中的元素压入sta2中,则5、6、7反而排在了2、3、4前面,会导致“队列”的元素顺序乱套。