剑指 Offer 09. 用两个栈实现队列
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )
很多人看不懂题目,博主刚开始也是萌萌,简单明了,带你直接看懂题目和例子。 输入: [“CQueue”,“appendTail”,“deleteHead”,“deleteHead”] 这里是要执行的方法,从左到右执行
[[],[3],[],[]]对应上面的方法,是上面方法的参数。CQueue和deleteHead方法不需要指定数字,但deleteHead要返回被删除元素,只有appendTail添加才需要指定数字,但无返回值:
1.创建队列,返回值为null
2.将3压入栈,返回值为null
3.将栈底的元素删除,也就是消息队列中先进来的元素,所以是deleteHead,返回该元素的数值,所以为3
4.继续删除栈底的元素,但是没有元素了,所以返回-1
所以就有了下面的输出 输出:[null,null,3,-1]
示例 2: 输入: [“CQueue”,“deleteHead”,“appendTail”,“appendTail”,“deleteHead”,“deleteHead”]
[[],[],[5],[2],[],[]]:
1.创建队列,返回值为null
2.删除栈底的元素,但是没有元素,所以返回-1
3.把5压入栈,返回null
4.把2压入栈,返回null
5.删除栈底的一个元素,也就是消息队列中先进来的元素,所以是deleteHead,就是最先进来的5,返回值为5,
6.删除栈底的一个元素,就是后进来的2,返回值为2,
所以就有了下面的输出
输出:[null,-1,null,null,5,2]
有没有发现先进来的数字,首先显示出来了,但是题目中说要使用栈,栈是先进后出的,使用栈来实现先进先出,在这里使用两个栈就好了,从一个进来再出去到另一个栈就是要删除的顺序,这样顺序就是先进先出了。题目的主旨写在第一句,就是,使用两个栈实现一个队列。
public class CQueue {
Stack<Integer> stack1;
Stack<Integer> stack2;
//创建队列,无参数,返回null
public CQueue() {
stack1 = new Stack<>();
stack2 = new Stack<>();
}
// appendTail 参数为value,将数据压入栈中无返回值;
public void appendTail(int value){
stack1.push(value);
}
// 删除先压入栈的值,返回这个值。若为null,返回-1
public int deleteHead(){
//使用if(stack2 == null) 错误
if(stack2.isEmpty()) {
//stack1.empty
while (!stack1.isEmpty()) {
//之前显示pop()返回是object类型,所以使用stack2.push(Integer.parseInt(stack1.pop().toString()));
stack2.push(stack1.pop());
}
}
/*else if(stack2.isEmpty()),如果写成这样,上面的if执行完了没有返回的语句,会提醒缺少return
if ,else if,else,是满足条件执行一个。下面改成if if是都会执行
return两个作用1.返回结果2.结束函数。
怎么使用return:当找到我想要的结果时
使用几个:循环找到就可使用提前结束循环,返回结果。循环结束没找到,也要返回return null
*/
if(stack2.isEmpty()){
return -1;
}
else{
int value = stack2.pop();
return value;
}
}
}
整体思路:
1、创建一个队列,需要用两个栈来实现
2.添加appendTail()中需要传入添加数据的参数,但无需返回值。用Stack的push直接压入栈底即可
3.删除deleteHead()不需传入参数,但需返回删除的元素值。Stack 是先进后出,与队列的性质先进先出不同,所以要再使用一个栈来控制删除的顺序,第一个栈是push进入的数据,顺序是先进的再最下面,而我们要将他最先删除,就需要借助第二个栈,让第一个栈中push进入的数据pop出去,这样最后进入的就在最下面,先进入的再最上面这样就可以完成删除的操作。
需要注意的是deleteHead()的注释部分是博主踩过的坑。
还有两个不理解的地方:
1.stack2 == null和stack2.isEmpty()不同吗?
应该是不能用==null判断为空,结果会出错。
2 stack1.empty()和stack1.isEmpty()不同之处?
java.util.Stack类中,size()方法是使用的java.util.Vector的size()方法,那么从源码上看,empty()和isEmpty()两者无本质区别。
当判断一个栈是否为空时,使用stack.empty()与stack.isEmpty()均可,只是两个方法存在的类不同。
3.之前显示pop()返回是object类型,所以使用stack2.push(stack1.pop())提示我需要类型转换。为什么只会就不提示了呢
因为提示要类型转换,所以特意搜集了两个object转integer的方法
1.先转为String类型,再转为Integer
Objcet obj;
int a= Integer.parseInt(obj.toString());
2.先把object强转成Long,再转为int
Object obj ;
Long long = (Long) obj;
int a= long.intValue();
如果你们有好的意见或者建议可以直接评论,希望有人可以解答我的疑惑!