剑指Offer09——用两个栈实现队列:思路分享
数组、栈、队列的互相实现,都是白给题哦,链接如下:
【Java实现】剑指Offer30——包含min函数的栈(LeetCode155:最小栈,左神基础班的白给题)
解题思路:
我们都知道,栈是先进后出的,那怎么用这样的结构实现队列先进先出的功能呢?
秘诀就是用两个栈
假设有两个栈,data
和help
如何实现:
每次队列要poll()
数据出去之前,只需将第一个栈data
中的数据,挨个pop()
出来,再push()
进辅助栈help
,这样顺序就颠倒过来了,再pop()
,就能达到和队列一样的效果。
例如:
数列1、2、3、4、5
按顺序进data
栈,按理来说出栈的顺序是5、4、3、2、1
,那此时我们将这五个数出栈,再装到准备好的辅助栈中,即help
的入栈顺序是5、4、3、2、1
,1
在栈顶,此时再从help
取元素的顺序,就相当于队列的先进先出了,是不是很聪明呢!
思路理顺之后,我们知道了关键的一步在于把数据从一个栈倒入另一个栈,这一步也是有几个注意事项的:
- 每次倒入操作一定要把数全倒掉,不能有遗留:假设留了一个数,如果此时
data
栈又进来一个数,就无法保证原始的顺序了 - 每次倒之前保证
help
栈为空:同样道理,如果不为空,新来的数据会打乱原来的顺序
综上两步,我们可以将倒数据这个步骤封装成单独的模块,甚至是离线脚本
代码如下:
class CQueue {
//定义两个栈
private Stack<Integer> data;
private Stack<Integer> help;
public CQueue() {
data=new Stack<>();
help=new Stack<>();
}
//在队尾插入整数
public void appendTail(int value) {
data.push(value);
}
//删除队列头部
public int deleteHead() {
if(help.isEmpty() && data.isEmpty()) {
//throw new RuntimeException("Queue is empty");
return -1;
}
dao();
return help.pop();
}
//把第一个栈的数据倒入第二个栈
private void dao() {
if(!help.isEmpty()) {
return;
}
while(!data.isEmpty()) {
help.push(data.pop());
}
}
//添加一个功能:查看最上方元素
private int peek() {
if(data.isEmpty() && help.isEmpty()) {
throw new RuntimeException("queue is empty");
}
dao();
return help.peek();
}
}
/**
* Your CQueue object will be instantiated and called as such:
* CQueue obj = new CQueue();
* obj.appendTail(value);
* int param_2 = obj.deleteHead();
*/