剑指offer-用两个栈实现队列-两个队列实现栈

题目描述

用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

思路:

用两个先进后出的栈来实现一个先进先出的队列。显然,出栈顺序和我们所求的出队列的顺序是相反的。
如果把第一个栈中的元素压入第二个栈,此时经历了压入——弹出——再压入,此时如果再弹出,则和我们所需要的队列 的弹出顺序是一致的。
当有数据要入队的时候,我们就让它压入stack1,要进行pop操作的时候,我们就把stack1里面的数据全部压入stack2中,
然后对stack进行一次pop操作就可以了,因为此时stack的栈顶就相当于队列的最先进来的数据
当然在pop操作里需要先判断两个栈是否都为空,而且当stack2不为空的话就可以直接进行stack2.pop(),
stack2为空但是stack1不为空在进行上面的操作)。

更清晰的思路参考这个博客:https://www.cnblogs.com/MrListening/p/5697459.html,画图也画的清晰明了。

代码1:

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
        stack1.push(node);
        
    }
    
    public int pop() {
        if(stack2.size()<=0){//stack2为空
    		while(stack1.size()>0){//stack1不为空
    			stack2.push(stack1.pop());
    		}
    	}
        if(stack2.isEmpty()){
    		try{
    			throw new Exception("queue is empty!");
    		}catch (Exception e) {
				// TODO: handle exception
			}
    	}
    	Integer head=stack2.pop();
    	return head;
    
    }
}

代码2:

与代码1不同之处就是pop的判断方式有所不同,但是思想都是一致的,关键之处在于下面这句话:

当然在pop操作里需要先判断两个栈是否都为空,而且当stack2不为空的话就可以直接进行stack2.pop(),
stack2为空但是stack1不为空在进行上面的操作)。

import java.util.Stack;

public class Solution {
    Stack<Integer> stack1 = new Stack<Integer>();
    Stack<Integer> stack2 = new Stack<Integer>();
    
    public void push(int node) {
      stack1.push(node);  
    }
    
    public int pop() {
        if(stack1.empty()&&stack2.empty()){
    		try {
				throw new Exception("queue is empty");
			} catch (Exception e) {
				// TODO: handle exception
			}
    	}
    	if(stack2.empty()){
    		while(!stack1.empty()){
    			stack2.push(stack1.pop());
    		}
    	}
    	
    	Integer head=stack2.pop();
		return head;
    
    }
}

题目衍生:

因为两个栈实现队列和两个队列实现栈的题目经常会一起被问到,所以也实现了一下用两个队列实现一个栈的方法。主要思路参考这个博客:

https://blog.csdn.net/sheepmu/article/details/38428205

思路:

压入栈:直接用队列的add()方法(相当于以前的addLast,添加新的元素到队尾的方法),不需要什么特殊的判断。

弹出栈:所有元素a,b,c进队列q1,我们的目的是栈,也就是最先c。而队是从队头出的。所以先把a,b出q1并放入q2,此时q1中的元素c跑到了队头,让c出q1.此时q1已经为空,下一个要出队的是b,因此把a从q2中出队并送入q1,此时q2中的b跑到了队头,出b。
总结为:把非空队列的前n-1个元素压入空队列,剩下最后一个(第n个元素)出队...最后总有一个队列为空 。

代码见下:

class TwoQueueToSatck {
	Queue<Integer> queue1 = new ArrayDeque<>();
    Queue<Integer> queue2 = new ArrayDeque<>();
    //入栈
    public void push(int value){
    	queue1.add(value);
    }
    //出栈
    public int pop(){  
    	//必须是非空才可以出栈
    	if(queue1.size()+queue2.size()!=0){
    		//q1不为空,将q1的前n-1个元素移动到q2中
    		if(!queue1.isEmpty()){
    			putN_1ToAnother();
    			return queue1.remove();
    		}else{
    			//q2不为空,将q2的前n-1个元素移动到q1中
    			putN_1ToAnother();
    			return queue2.remove();
    		}
    		
    	}
    	else{
    		System.out.println("栈为空,不能出栈");
    		return -1;
    	}
    }

	private void putN_1ToAnother() {
		//从非空队列中出前n-1个到空队列(队列总是一空一非空)
		// TODO Auto-generated method stub
		if(!queue1.isEmpty()){
			while(queue1.size()>1){
				queue2.add(queue1.remove());
			}
		}else{
			if(!queue2.isEmpty()){
				while(queue2.size()>1){
					queue1.add(queue2.remove());
				}
			}
		}
		
		
	}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值