前言
leetcode上,剑指offer,用两个栈实现队列:
题目地址
1.基础知识
1.1 数据结构:栈
栈是一种数据结构,简单来说,数据像大饼一样被叠放在一起,数据只能放在栈的最上方,在取出数据的时候,只能从最上方取。栈中,添加数据的时候,就叫做入栈,取出数据的时候就叫做出栈,如下图所示:
1.1 数据结构:队列
队列与栈类似,也是一种数据结构,一种特殊的线性表,和栈不同的是,队列的插入操作只允许在队列的前端进行,队列的插入操作,只允许在队列的后端进行,如下图所示:
2.解题思路
一个栈实现插入,一个栈实现删除
通过上面基础知识可以看到,栈和队列的插入是一样的,来一个元素,直接加入栈或者队列就好,差别在于删除,栈是先进后出,最先来的数据是最后删除的,但是队列不一样,最先进入队列的元素是最先删除的,顺序是反着的,因此我们可以使用两个栈。一个栈来实现队列的插入,一个栈来实现队列的删除。
实现队列的插入的栈不需要进行额外的处理,实现队列的删除的栈则需要把插入栈中的元素顺序反过来,这样就是队列的先入先出了,具体则是,当需要删除时,把插入栈中的数据一个一个取出来,放到删除栈中,然后再取出删除栈中的一个数据,这样就实现了队列的删除元素功能。
注意,删除完毕一个数据之后,删除栈中的元素不用再弹回插入栈了,因为你后面删除的时候还要再弹回来,就多此一举了,具体JAVA代码如下:
class CQueue{
Deque<Integer> stack1; //插入栈
Deque<Integer> stack2; //删除栈
public CQueue(){
stack1 = new LinkedList<Integer>();
stack2 = new LinkedList<Integer>();
}
//定义队列的插入方法
//直接用插入栈插入
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{
int deleteItem = stack2.pop();
return deleteItem;
}
}
}
关键点在于:题目中说了,用栈实现队列,也就是JAVA中的栈的数据结构可以直接使用,栈的相关方法要熟悉,才能真正的实现这个队列的类。
需要注意的是,在插入栈往删除栈里面弹数据的时候,一定要判断删除栈里面的数据是否已经弹完了,如果没有弹完,那么删除栈里面的数据就不能再往里面加了,如果往里面加,那弹出的顺序就错了。
该方法的空间复杂度O(n),时间复杂度,插入操作明显是O(1),对于删除操作,也是O(1),因为每个数据最多被插入、弹出删除栈一次。