「剑指Offer 09 用两个栈实现队列」
题目描述(level 简单)
用两个栈实现一个队列。队列的申明如下,请实现它的两个函数 appendTail
和 deleteHead
,分别完成在队列的尾部插入整数和在队列的头部删除整数的功能。(若队列中没有元素,deleteHead
操作返回-1
)。
示例
输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]
输入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]
思路分析
- 栈结构的特点,先进后出,而队列则是先进先出,对于栈底部的元素(先添加进去的元素),要想删除,首先必须将元素上的元素全部弹出(出栈)才可以进行删除操作。
- 题目要求删除队列头部元素,并且使用两个栈来实现,假设两个栈分别为A、B,其中B为辅助空栈,删除队列头部元素即是删除A栈的底部元素,可以想到,将A中的元素全部弹出并对B进行压栈操作,此时B的栈顶元素就是A的栈底元素,进行删除操作即可。
- 对于添加操作
appendTail
(添加到队列尾),则直接添加到A中即可。
代码实现
public class CQueue {
private final Deque<Integer> stack1;
private final Deque<Integer> stack2;
public CQueue() {
stack1 = new LinkedList<>();
stack2 = new LinkedList<>();
}
public void appendTail(int value) {
stack1.push(value);
}
public int deleteHead() {
if (stack2.isEmpty()) {
while (!stack1.isEmpty()) {
stack2.push(stack1.pop());
}
}
if (stack2.isEmpty()) {
return -1;
} else {
return stack2.pop();
}
}
}
解释
- 假设CQueue初始化为空,向其中添加三个元素1、2、3,此时A = [1,2,3],执行deleteHead则需要删除元素1。则执行操作后A = [],而B = [3,2].如果此时添加一个元素4,那么A = [4].划重点,如果是黑盒情况下,此时我们知道队列中的数据应该是 [2,3,4] 因为1被删除了,4被后加入的。带入到代码中,此时执行
deleteHead
因为B不为空,此时直接弹出2即可。 - 可以这么理解,删除操作需要首先对B进行判空,不为空,则已经完成倒序了,删除头部直接弹出即可。为空时需要判断A是否为空,不为空则需要进行倒序处理,如果A、B均为空,直接返回 -1。