文章目录
剑指 Offer 09. 用两个栈实现队列
题目概述:
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
示例 1:
输入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出:[null,null,3,-1]
示例 2:
输入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]
提示:
1 <= values <= 10000
最多会对 appendTail、deleteHead 进行 10000 次调用
算法思路:
-
题目要求用两个栈实现队列,由栈的性质可知先进后出,所以可以先用一个栈存储数据(添加方法)
-
然后在删除的时候将该栈所有的元素出栈,并且将出栈的所有元素重新压入到新栈中,这样新栈出栈后的元素排列顺序与原顺序相同
原排列: 1 2 3 4 5 存储栈: 压入: 1 2 3 4 5(栈顶) 弹出: 5 4 3 2 1 删除栈: 压入: 5 4 3 2 1(栈顶) 弹出: 1 2 3 4 5(还原)
-
具体步骤如下
-
遇到添加方法,则将元素压入到存储栈中
-
遇到删除方法,则先判断删除栈的元素弹出
-
否则,判断存储栈是否为空,如果存储栈为空,则返回-1;如果存储栈不为空,则将存储栈的所有元素弹出后压入到删除栈中
-
然后弹出删除栈的栈顶元素
复杂度分析:
- 时间复杂度:对于插入和删除操作,时间复杂度均为 O(1)。插入不多说,对于删除操作,虽然看起来是 O(n) 的时间复杂度,但是仔细考虑下每个元素只会「至多被插入和弹出 stack2 一次」,因此均摊下来每个元素被删除的时间复杂度仍为 O(1)O(1)。
- 空间复杂度:O(n)。需要使用两个栈存储已有的元素。
代码实现:
class CQueue {
LinkedList<Integer> rear = null;
LinkedList<Integer> front = null;
public CQueue() {
rear = new LinkedList<>();
front = new LinkedList<>();
}
public void appendTail(int value) {
front.push(value);
}
public int deleteHead() {
if(!rear.isEmpty()){
return rear.pop();
}
else{
if(front.isEmpty()){
return -1;
}
while(!front.isEmpty()){
rear.push(front.pop());
}
return rear.pop();
}
}
}