问题描述
使用栈实现队列的下列操作:
- push(x) – 将一个元素放入队列的尾部。
- pop() – 从队列首部移除元素。
- peek() – 返回队列首部的元素。
- empty() – 返回队列是否为空。
示例
MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false
说明:
- 你只能使用标准的栈操作 – 也就是只有 push to top, peek/pop from top, size, 和 is empty操作是合法的。
- 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
- 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
思路
设置两个栈,一个作为主栈,一个作为辅助栈。模拟队列时,入队时直接入主栈。 获取队头或者是出队时,先将主栈中所有东西倒入辅助栈,然后把栈底元素记录下来或者弹出,再把辅助栈中的东西全部倒入主栈。
总而言之就是,辅助栈中不存储东西,只是临时存储,只是为了弹出或者是取队头而用的一个临时存储区。(方法一)
这个方法花费了1ms。有点慢。想了想怎么优化。咦,卧槽。把主栈的东西倒到辅助栈的时候,我何必再把它倒回去呢?因为此时辅助栈就变成了一个"队列"了啊。先"入队"的元素在辅助栈的栈顶了。
所以,改进算法:辅助栈为空时,把主栈的所有东西都倒到辅助栈中。在出队或者是取队头时,如果辅助栈不为空,证明这个"假队列"还有效,直接弹栈。如果为空,则把主栈的所有东西都倒进来。
那么,入队的时候是入到主栈还是辅助栈呢? 当然是入到主栈了。 在这个结构中,主栈的栈顶永远是最后入队的元素,辅助栈的栈顶永远是最先入队的元素。
那么,判空呢? 两个栈都为空才算队空。(方法二)
方法一
Java版
class MyQueue {
Stack<Integer> main = new Stack<>();
Stack<Integer> aid = new Stack<>();
/** Initialize your data structure here. */
public MyQueue() {
}
/** Push element x to the back of queue. */
public void push(int x) {
main.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
while(main.size() > 1){
aid.push(main.pop());
}
int res = main.pop();
while(!aid.isEmpty()){
main.push(aid.pop());
}
return res;
}
/** Get the front element. */
public int peek() {
while(main.size() > 1){
aid.push(main.pop());
}
int res = main.peek();
while(!aid.isEmpty()){
main.push(aid.pop());
}
return res;
}
/** Returns whether the queue is empty. */
public boolean empty() {
return main.isEmpty();
}
}
方法二
Java版
class MyQueue {
Stack<Integer> stack = new Stack<>();
Stack<Integer> queue = new Stack<>();
/** Initialize your data structure here. */
public MyQueue() {
}
/** Push element x to the back of queue. */
public void push(int x) {
stack.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
if(queue.isEmpty()){
while(!stack.isEmpty()){
queue.push(stack.pop());
}
}
return queue.pop();
}
/** Get the front element. */
public int peek() {
if(queue.isEmpty()){
while(!stack.isEmpty()){
queue.push(stack.pop());
}
}
return queue.peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
return queue.isEmpty()&&stack.isEmpty();
}
}