问题描述:
Implement the following operations of a stack using queues.
- push(x) -- Push element x onto stack.
- pop() -- Removes the element on top of the stack.
- top() -- Get the top element.
- empty() -- Return whether the stack is empty.
Notes:
- You must use only standard operations of a queue -- which means only
push to back
,peek/pop from front
,size
, andis empty
operations are valid. - Depending on your language, queue may not be supported natively. You may simulate a queue by using a list or deque (double-ended queue), as long as you use only standard operations of a queue.
- You may assume that all operations are valid (for example, no pop or top operations will be called on an empty stack).
link: https://leetcode.com/problems/implement-stack-using-queues/
解决思路:
<思路1>
假设有两个队列,分别为q1和q2. 对数据元素进行操作时使用q1,将q2作为辅助的数据缓存的队列。具体做法如下:
(1) push时,直接将需要push的元素加到q1中;
(2) pop时,首先检查q1是否为空,如果不为空则将q1中的元素都poll到q2中,直到q1中的元素剩余一个为止,剩下的这个元素即为需要pop的元素,poll即可;
(3) peek时,与(2)中的pop类似,区别在于最后不poll,保留该值,最终返回即可。
(4) isEmpty()只需要检查q1.size()是否为0;
<代码>
class MyStack { private Queue<Integer> q1; private Queue<Integer> q2; public MyStack() { q1 = new LinkedList<Integer>(); q2 = new LinkedList<Integer>(); } // Push element x onto stack. public void push(int x) { q1.offer(x); } // Removes the element on top of the stack. public void pop() { if (q1.size() == 0) { return ; } while (q1.size() > 1) { q2.offer(q1.poll()); } q1.poll(); while (q2.size() > 0) { q1.offer(q2.poll()); } } // Get the top element. public int top() { if (q1.size() == 0) { return -1; } while (q1.size() > 1) { q2.offer(q1.poll()); } int res = q1.poll(); q2.offer(res); while (q2.size() > 0) { q1.offer(q2.poll()); } return res; } // Return whether the stack is empty. public boolean empty() { return q1.size() == 0; } }
<思路2>
思路1中每次pop操作之后,都要将q2中的元素倒回q1中,这样做的的优点可以使得push操作更简单,但是缺点在于效率不高。下面考虑另一种思路,使用两个指针pushTmp和tmp来标记进出栈操作对应的队列和中间缓存的队列,只要这两种类型的队列确定了,对应的pop和push操作和思路1中的是一样的。tmp对应的队列通常为空。
<代码>
class MyStack { private Queue<Integer> q1; private Queue<Integer> q2; private Queue<Integer> pushTmp; private Queue<Integer> tmp; public MyStack() { q1 = new LinkedList<Integer>(); q2 = new LinkedList<Integer>(); } // Push element x onto stack. public void push(int x) { if (q1.size() == 0) { pushTmp = q2; } else { pushTmp = q1; } pushTmp.offer(x); } // Removes the element on top of the stack. public void pop() { if (q1.size() == 0) { tmp = q1; pushTmp = q2; } else { tmp = q2; pushTmp = q1; } if (pushTmp.size() == 0) { return ; } while (pushTmp.size() > 1) { tmp.offer(pushTmp.poll()); } pushTmp.poll(); } // Get the top element. public int top() { if (q1.size() == 0) { tmp = q1; pushTmp = q2; } else { tmp = q2; pushTmp = q1; } if (pushTmp.size() == 0) { return -1; } while (pushTmp.size() > 1) { tmp.offer(pushTmp.poll()); } int res = pushTmp.poll(); tmp.offer(res); return res; } // Return whether the stack is empty. public boolean empty() { return q1.size() == 0 && q2.size() == 0; } }
拓展问题:两个栈实现一个队列
<思路1>
假设有两个栈分别为S1和S2,按照以下方法来模拟队列:
(1) 元素进队列:直接将元素push到S1中;
(2) 元素出队列:首先检查S2是否为空,如果不为空则S2.pop()即可;如果为空,则将S1中的所有元素都pop并且push到S2中(如果S1为空则抛出抛出异常)。
<代码>
class MyQueue{ private Stack<Integer> s1; private Stack<Integer> s2; public MyQueue() { s1 = new Stack<Integer>(); s2 = new Stack<Integer>(); } public void offer(int elem){ s1.push(elem); } public int poll() { if (!s2.isEmpty()) { return s2.pop(); } if (s1.isEmpty()) { return -1; } while (!s1.isEmpty()) { s2.push(s1.pop()); } return s2.pop(); } public int peek() { if (!s2.isEmpty()) { return s2.peek(); } while (!s1.isEmpty()) { s2.push(s1.pop()); } return s2.peek(); } }