掘金团队号上线,助你 Offer 临门! 点击 查看详情
一、题目描述
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
示例:
输入
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
输出
[null,null,3,-1]
限制
1 <= values <= 10000
最多会对 appendTail、deleteHead 进行 10000 次调用
二、思路分析
我的思路
- 先使用一个队列专门用来append的。
- 当需要删除的时候,就需要将最下面的一个拿出来,此时就使用另一个栈存放上面的元素,弹出后,然后再将之前的元素放回去。
- 这个很显然最简单的思路了。肯定可以优化。
- 我的做法其实,put和delete都指望在一个栈完成!另外一个栈只是用来辅助的,想的太复杂了(其实就是想得太笨了)。
最佳思路
- 思路大都一致:但是我的思路多了第二个循环再放回去这步骤!
- 使用一个栈,专门用来append到来的数据。另外一个栈专门用来delete。
- 比如主要append的栈为A,负责delete的栈为B。那么put的时候,即往栈压入A,当需要删除的时候,需要删除的元素在A的最下面,此时我们需要将上面的元素全部放入B中!
- 这时候就很关键了:当需要继续put的时候,我们只要继续往A继续put就行了,并不需要将之前压入B的都取出来,那没有意义。
- 然后进行删除的时候,我们从B取最上面的元素,当B没有了的时候,我们再执行一次将A全部压入B的操作
- (其实道理也很简单,但是脑子一时没有转过这个弯)
三、AC 代码
Stack<Integer> mainStack;
Stack<Integer> backupStack;
public CQueue() {
// 使用2个栈构建队列
mainStack = new Stack<>();
backupStack = new Stack<>();
}
public void appendTail(int value) {
// put只往main栈put
mainStack.push(value);
}
// 我的写法
public int deleteHead() {
if (mainStack.isEmpty()) {
return -1;
}
// 主栈不为空的话,就将main的数据先put到backup
while (!mainStack.empty()) {
backupStack.push(mainStack.pop());
}
// 然后弹出backup最上面的
int res = backupStack.pop();
// 然后再将元素放回去。。。。。。😓
while (!backupStack.empty()) {
mainStack.push(backupStack.pop());
}
return res;
}
// 最佳写法
public int deleteHeadGood() {
// 删除直接从backup删除,如果backup是空的,那么就将main当前所有的元素都压入到backup中
if (backupStack.isEmpty()) {
if (mainStack.isEmpty()) {
return -1;
}
while (!mainStack.isEmpty()) {
backupStack.push(mainStack.pop());
}
}
return backupStack.pop();
}
四、总结
核心点:记住2个栈,让一个栈负责接收put,另外一个栈负责delete。