用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
示例 1:
输入: ["CQueue","appendTail","deleteHead","deleteHead","deleteHead"] [[],[3],[],[],[]] 输出:[null,null,3,-1,-1] 示例 2:
输入: ["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"] [[],[],[5],[2],[],[]] 输出:[null,-1,null,null,5,2] 提示:
1 <= values <= 10000 最多会对 appendTail、deleteHead 进行 10000 次调用
解法一:
解题思路:
- 栈无法实现队列功能: 栈底元素(对应队首元素)无法直接删除,需要将上方所有元素出栈。
- 双栈可实现列表倒序: 设有含三个元素的栈 A=[1,2,3] 和空栈 B=[]。若循环执行 A 元素出栈并添加入栈 B ,直到栈 A 为空,则 A=[] , B=[3,2,1] ,即 栈 B 元素实现栈 A 元素倒序 。
- 利用栈 B 删除队首元素: 倒序后,B 执行出栈则相当于删除了 A 的栈底元素,即对应队首元素。
函数设计:
题目只要求实现 加入队尾 appendTail() 和 删除队首 deleteHead() 两个函数的正常工作,因此我们可以设计栈 A 用于加入队尾操作,栈 B 用于将元素倒序,从而实现删除队首元素。
-
加入队尾 appendTail()函数: 将数字 val 加入栈 A 即可。
-
删除队首deleteHead()函数: 有以下三种情况。 当栈 B 不为空:B 中仍有已完成倒序的元素,因此直接返回 B 的栈顶元素。 否则,当 A 为空: 即两个栈都为空,无元素,因此返回 −1。 否则:将栈 A 元素全部转移至栈 B 中,实现元素倒序,并返回栈 B 的栈顶元素。
复杂度分析:
由于问题特殊,以下分析仅满足添加 N 个元素并删除 N 个元素,即栈初始和结束状态下都为空的情况。
时间复杂度:
-
appendTail()函数为 O(1) ;
-
deleteHead() 函数在 N 次队首元素删除操作中总共需完成 N 个元素的倒序。
空间复杂度 O(N) : 最差情况下,栈 A 和 B 共保存 N 个元素。
class CQueue {
Stack<Integer> stack1;
Stack<Integer> stack2;
public CQueue() {
stack1 = new Stack<>();
stack2 = new Stack<>();
}
public void appendTail(int value) {
stack1.push(value);
}
public int deleteHead() {
if (!stack2.empty()) {
return stack2.pop();
} else {
if (stack1.empty()) {
return -1;
} else {
while (!stack1.empty()) {
int value = stack1.pop();
stack2.push(value);
}
return stack2.pop();
}
}
}
}