- 我的思路比较蠢,用两个栈,第一个栈 A 就正常 push,等于逆序存储了队列的值,在 push 或 peek 时,把栈 A 的值 pop 并 push 到另一个栈 B,栈 B 存储的就是正确顺序的队列的值,pop 或 peek 完了之后再把 B 的 pop 回 A。
-
class MyQueue { Stack<Integer> stack = new Stack<>(); Stack<Integer> queue = new Stack<>(); public MyQueue() { } public void push(int x) { stack.push(x); } public int pop() { while(!stack.isEmpty()){ queue.push(stack.pop()); } int val = queue.pop(); while(!queue.isEmpty()){ stack.push(queue.pop()); } return val; } public int peek() { while(!stack.isEmpty()){ queue.push(stack.pop()); } int val = queue.peek(); while(!queue.isEmpty()){ stack.push(queue.pop()); } return val; } public boolean empty() { return stack.isEmpty(); } }
- 但是如果连续多次 pop 或 peek 时,其实我们不需要每次都把数据来回倒腾一遍,定义一个布尔值记录当前是否是顺序存储,pop 或 peek 如果不为顺序就搞成顺序,否则直接 pop 或 peek 即可,push 时如果为顺序就再倒腾回来,否则直接 push。
-
class MyQueue { Stack<Integer> stack = new Stack<>(); Stack<Integer> queue = new Stack<>(); boolean isAsc; public MyQueue() { } public void push(int x) { if(isAsc){ isAsc = false; while(!queue.isEmpty()){ stack.push(queue.pop()); } } stack.push(x); } public int pop() { if(isAsc){ return queue.pop(); } isAsc = true; while(!stack.isEmpty()){ queue.push(stack.pop()); } return queue.pop(); } public int peek() { if(isAsc){ return queue.peek(); } isAsc = true; while(!stack.isEmpty()){ queue.push(stack.pop()); } return queue.peek(); } public boolean empty() { return stack.isEmpty() && queue.isEmpty(); } }
+在上面我之所以一旦在 pop 或 peek 操作后再 push,就要把元素重新从 queue pop 回 stack,就是为了保持 stack 的倒序存储,保证了 stack 的倒序,在需要 pop 或 peek 就能重新 pop 回 queue,保证了 queue 的顺序存储。但是实际上不需要这么复杂,当遇到 pop 或 peek 操作时,只要 queue 为空就把 stack 的元素都 pop 到 queue,当 push 时就只需要正常 push 到 stack 即可,这样的话当你 pop 或 peek 时,你只有把之前顺序存储的元素用完了才会再从 stack 取元素。用完了才再填充这一件事,就是保持 stack 和 queue 按照正确顺序存储元素的关键。比如正常入队元素为 [1,2,3],stack 在 push 完 [1,2] 后为 [2,1],这时我 pop,queue 就开始填充为 [1,2],然后 pop 出 1 剩余 [2],stack 此时为 [],如果我 push 完 3 后再 pop,直接就再把 3 填充到 queue 的 [2],就成了[3,2] 然后 pop queue 的 3,实际上应该 pop 2 才对,而我把 queue 用完上一轮正确存储的元素再存储后就保证了使用 queue 的元素时,顺序都是正确的,也就是先 pop 了 1, 然后 pop 2,等到没东西 pop 了才把 stack 的 3 拿过来 pop。
-
Stack<Integer> stack = new Stack<>(); Stack<Integer> queue = new Stack<>(); public MyQueue() { } public void push(int x) { stack.push(x); } public int pop() { fillQueue(); return queue.pop(); } public int peek() { fillQueue(); return queue.peek(); } public boolean empty() { return stack.isEmpty() && queue.isEmpty(); } public void fillQueue(){ if(queue.isEmpty()){ while(!stack.isEmpty()){ queue.push(stack.pop()); } } }