队列与栈复习II——相互实现

225. 用队列实现栈

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

方法一:两个队列

两个队列,入队都入q1,每次pop/peek除了最后一个都移入另一个队列,区别在于peek完还要重新入队

class MyStack {
    Queue<Integer>q1;
    Queue<Integer>q2;
    public int size;
    public MyStack() {
        q1=new LinkedList<>();
        q2=new LinkedList<>();
        size=0;
    }
    
    public void push(int x) {
        q1.offer(x);
        size++;
    }
    
    public int pop() {
        size--;
        if(q1.size()==0){
            while(q2.size()>1){
                q1.offer(q2.poll());
            }
            return q2.poll();
        }
        while(q1.size()>1){
            q2.offer(q1.poll());
        }
        return q1.poll();
    }
    
    public int top() {
        if(q1.size()==0){
            while(q2.size()>1){
                q1.offer(q2.poll());
            }
            return q2.peek();
        }
        while(q1.size()>1){
            q2.offer(q1.poll());
        }
        int res=q1.peek();
        q2.offer(q1.poll());
        return res;
    }   
    public boolean empty() {
        return size==0;
    }
}

方法二:一个队列

很简单,就是记录栈的大小,入栈就直接offer即可,pop的时候要的是最后入队的元素,总共有n个元素,我们将n-1个元素出队再入队,那么原先最后入队的元素此时就在队尾,如果pop就直接poll,如果peek就peek完将其重新入队,保持原结构不变。

class MyStack {
    Queue<Integer>q;
    public int size;
    public MyStack() {
        q=new LinkedList<>();
        size=0;
    }
    
    public void push(int x) {
        q.offer(x);
        size++;
    }
    
    public int pop() {
        size--;
        for(int i=0;i<size;i++){
            q.offer(q.poll());
        }
        return q.poll();
    }
    
    public int top() {
        for(int i=0;i<size-1;i++){
            q.offer(q.poll());
        }
        int top=q.peek();
        q.offer(q.poll());
        return top;
    }   
    public boolean empty() {
        return size==0;
    }
}

232. 用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false

这个题目和225不同,区别在于队列有两个口,可以一进一出,一个队列可以同时实现进出功能,但是栈只有一个口,一个栈无论如何是无法实现双口队列的,所以必须要用两个栈来实现

方法一:用两个栈,一个用来输入数据,一个用来输出数据,我们可以认为,队列的先进先出输出模式符合人类的正常思维,所以栈实际上是一次倒序输出,而两次倒序,自然就是正序输出了,正向输入instack,再输出到outstack,最后输出outstack即可
 

class MyQueue {
    Stack<Integer> inStack;
    Stack<Integer> outStack;
    int size;
    public MyQueue() {
        inStack = new Stack<Integer>();
        outStack = new Stack<Integer>();
        size=0;
    }
    public void push(int x) {
        size++;
        inStack.push(x);
    }
    
    public int pop() {
        for(int i=0;i<size;i++){
            outStack.push(inStack.pop());
        }
        int res=outStack.pop();
        size--;
        for(int i=0;i<size;i++){
            inStack.push(outStack.pop());
        }
        return res;
    }
    
    public int peek() {
        for(int i=0;i<size;i++){
            outStack.push(inStack.pop());
        }
        int res=outStack.peek();
        for(int i=0;i<size;i++){
            inStack.push(outStack.pop());
        }
        return res;
    }
    
    public boolean empty() {
        return size==0;
    }
}

优化:我们实际上不需要倒来倒去,oustack装的就是符合队列性质的数据,直接用来输出即可,等没法再输出了,再把instack的数据装入outstack中即可

class MyQueue {
    Stack<Integer> inStack;
    Stack<Integer> outStack;
    int size;
    public MyQueue() {
        inStack = new Stack<Integer>();
        outStack = new Stack<Integer>();
        size=0;
    }
    public void push(int x) {
        size++;
        inStack.push(x);
    }
    
    public int pop() {
        //我们不必每次都倒来倒去,队列先进先出,
        //所以我们一次性装进outstack之后,outstack内的数据就符合队列了
        //直到outstack空了,才需要加入新数据
        if(outStack.isEmpty()){
            for(int i=0;i<size;i++){
                outStack.push(inStack.pop());
            }
        }
        size--;
        return outStack.pop();
    }
    public int peek() {
        if(outStack.isEmpty()){
            for(int i=0;i<size;i++){
                outStack.push(inStack.pop());
            }
        }
        return outStack.peek();
    }   
    public boolean empty() {
        return size==0;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值