一、题目描述
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
例如:
# Input
["PSH1","PSH2","PSH3","POP","POP","PSH4","POP","PSH5","POP","POP"]
# Ouput
1,2,3,4,5
二、代码
思路:这道题稍微需要思考一下,需要想想如何利用两个堆栈(先进后出–FILO)来达到队列先进先出–FIFO的特性。
版本1.0(错误)
其中一个方案,步骤如下:V1
S1:将节点加入stack1,在此实现push(int node);
S2:将stack1的节点放入stack2.在此把顺序倒过来,先入后出*2 ==> 先入先出。然后pop();
问题:但针对这里得保证先全部push(),然后全部pop(),否则丢出的节点很可能就不满足队列特性了。
// 下面代码无法通过,可自己动手试试上面的例子。
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.add(node);
}
public int pop() {
int tmp;
while(!stack1.empty()) {
stack2.add(stack1.pop());
}
tmp = stack2.pop();
return tmp;
}
}
版本1.5:My
思路:改良上面步骤 V1.5
S1:将stack2全部节点先倒入stack1,然后再放节点;
S2:不变同上。
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
while(!stack2.empty()) {
stack1.add(stack2.pop());
}
stack1.add(node);
}
public int pop() {
int tmp;
while(!stack1.empty()) {
stack2.add(stack1.pop());
}
tmp = stack2.pop();
return tmp;
}
}
版本2:参考 ProJay
问题:上面代码显得不太清晰,起始过程容易被搞蒙。所以将stack2的节点再放入stack1放到pop()中。步骤如下:V2
S1:将节点加入stack1,在此实现push(int node);
S2:将stack1的节点放入stack2.在此把顺序倒过来,先入后出*2 ==> 先入先出。为保证下一步stack1()的push(int node)是按顺序的,再把节点从stack2倒回stack1中。然后pop();
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
while(!stack2.isEmpty())
{
return stack2.pop();
}
while(!stack1.isEmpty())
{
stack2.push(stack1.pop());
}
return stack2.pop();
}
}
版本3:参考侯夏冰(左程云《程序员代码面试指南》)
问题:上面的代码需要在stack1与stack2来回导,这来回导的操作其实可以省略。
步骤如下:V3
S1:不变同上。
S2:pop()时判断一些stack2是否为空,空则从stack1导入stack2,否则暂时存放在stack1中。
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(stack1.empty()&&stack2.empty()){
throw new RuntimeException("Queue is empty!");
}
if(stack2.empty()){
while(!stack1.empty()){
stack2.push(stack1.pop());
}
}
return stack2.pop();
}
}
完整简单测试小程序:
import java.util.Stack;
import java.util.Scanner;
class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.add(node);
}
public int pop() {
if(stack2.empty()) {
while(!stack1.empty()) {
stack2.add(stack1.pop());
}
}
return stack2.pop();
}
}
public class Main {
public static void main(String[] args) {
int num, tmp, cnt=0;
Solution solu = new Solution();
Scanner input = new Scanner(System.in);
num = input.nextInt();
while(num!=-1) {
cnt++;
solu.push(num);
num = input.nextInt();
}
for(int i=cnt;i>0;i--) {
tmp = solu.pop();
System.out.print(tmp + " ");
}
}
}
# Input
1 2 3 -1
# Output
1 2 3
三、小结
从这几个版本可以看到有时候一个小小的题目都可以充满各种小小的精巧的构思。这里面有些东西往往是你没看过就可能真的永远想不到,所以多看一些别人优秀的源码非常有必要,这是提高自己程序素养的必要手段。