一、题目描述:用两个栈实现一个队列
二、题目解析:
解法一:
大体思路:利用栈的特点,一个栈为主栈,是存放整个队列的所有元素的,当操作入队时,可以在主栈里push(入栈)一下;如果要操作出队时就再使用一个副栈,用来倒腾的,先将主栈里的所有元素push到副栈中,在获取副栈的第一个出栈元素即为队列的第一个出队元素,但要再倒腾回去,即将副栈剩下的元素push到主栈中,以备下次操作入栈是即可跟着当前的数据状态入栈。
缺点:时间复杂度高,倒腾的次数太多,每一次出队时要倒腾一次,如果连续多次出队时,就倒腾多次。为了减少倒腾的次数,所以第二种方法出现了。(具体代码我就不写了,以免有抄袭的嫌疑(哈哈^_^),其他人的博客的代码很好,大家可以查查,前两种方法我重点介绍思路,第三种方法我重点介绍思路和代码,也就是最优解的代码)
解法二:如果是连续的出队的话,可以从第一种方法上改进一下。就是再副栈中出栈了一个元素,如果下一次还是出队操作就继续从副栈中pop(出栈),避免了不必要的倒腾了。
解法三:这种方法是此题的最优解。思路就是,分析清楚了队列操作的本质,就是入队和出队这两种操作,既然是两种操作状态的话,就可以想象成是两种批次处理的(不是出对批次就是入队批次,这里批次的含义是要么是单个操作,要么是连续操作),那么在两个相同批次之间就必须夹着一个另一种批次操作。这样得话就可以使用两个栈来代表两种不同的批次操作,stackPush栈是入队批次操作的数据容器,stackPop栈是出队操作的数据容器,如果入队时直接在stackPush栈中push进去,如果要出队时就将判断stackPop栈是否为空,如果为空就把stackPush栈全部倒腾到stackPop栈里,否则直接stackPop出栈。
具体实现代码:
import java.util.Stack;
/*
* 题目描述:用两个栈实现一个队列
*/
public class TwoStackQueue {
/*
* 解题思路:用两个栈来分批次操作,保证两个入队批次之间夹着一个出队批次,
* 将这个出队批次放在了stackPop这个栈中,如果这个栈为空时,再将下一个出队批次
* 放进来,此时是所有方法里的最优解
*/
private Stack<Integer> stackPush;
private Stack<Integer> stackPop;
public TwoStackQueue(){
stackPush = new Stack<Integer>();
stackPop = new Stack<Integer>();
}
//入队
public void add(int pushInt) {
stackPop.push(pushInt);
}
//出队
public int poll() {
if(stackPop.empty()&&stackPush.empty()) {
throw new RuntimeException("Queue is empty");
}else if(stackPop.empty()) {
while (!stackPush.empty()) {
stackPop.push(stackPush.pop());
}
}
return stackPop.pop();
}
}