【五一创作】代码随想录Day10-栈与队列01 232. 用栈实现队列 225. 用队列实现栈

232. 用栈实现队列

        java中栈的数据结构是Stack,代码中使用的几个方法:

        push(x):将x压入栈

        pop():将栈顶元素弹出并返回该栈顶元素的值

        empty():判断栈是否为空

        peek():只返回栈顶元素的值,但是不弹出该元素

        这个队列由st1、st2两个栈实现,其中st1表示输入栈,用来存输入到队列中的数据,st2表示输出栈,每次数据出队列,就从st2栈顶使用pop()方法出栈。

        对于pop()方法的实现,我一开始的想法是,模拟入队列就是直接往st1里面push,模拟出队列因为要先进先出(FIFO),而栈又只能先进后出(FILO),因此每次出队列的时候都把st1的数全都放到st2中,取出栈顶元素,即队首元素后再把st2中元素全放回st1中。

        为什么会这么想我也不知道,绝了,而且执行用时居然也是0ms,但是每次都要来回倒数据,真的离谱,但凡数据量大点肯定撑不住了。

        就。。看了看人家想的。。果然。。

        直接判断一下st2里面是不是空的就好了呀!!!如果不空就直接出栈,这时候肯定是队首元素,如果空了就把st1里的数据全转移过去,这样st1栈底元素也就是此时的队首就成了st2栈顶元素,直接弹出就好了。

        empty()就看两个栈是不是同时是空的就好了,但凡一个栈有数据,队列肯定不是空的。

        还有一点就是,这段代码中存在重复代码,可以抽取成一个函数,就不用重复写了。

class MyQueue {
    Stack<Integer> st1;
    Stack<Integer> st2;

    public MyQueue() {
        st1 = new Stack<>();
        st2 = new Stack<>();
    }
    
    public void push(int x) {
        st1.push(x);
    }
    
    public int pop() {
        if(st2.empty()){
            while(!st1.empty()){
                int temp = st1.pop();
                st2.push(temp);
            }
        }
        int start = st2.pop();
        return start;
    }
    
    public int peek() {
        if(st2.empty()){
            while(!st1.empty()){
                int temp = st1.pop();
                st2.push(temp);
            }
        }
        return st2.peek();
    }
    
    public boolean empty() {
        return st1.empty() && st2.empty();
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */

        emmm有个小问题,就是为什么在类里创建了一个Stack对象,又到了构造方法里才用new创建一个栈呢,为啥不在类里面直接new好,等解决这个问题回来回答,嘤嘤嘤。

        还有个问题,官解用的是Deque<Integer> inStack; inStack = new ArrayDeque<Integer>();为什么不用Stack呢,qwq。问题太多了

225. 用队列实现栈

        !!!!!这个题,这个题,有个好思路真的很重要,我自己想了半天都没搞明白,写了依托答辩,最后跑出来是错的,放上来做个错误的示范。。

        当时怎么想的类,又想多了,大概就是新元素都放到q1里,q1每多一个元素size就++,当要pop的时候,就从q1里取元素放到q2直到q1只剩一个元素,就把这个元素poll出去,再把q2里的数据放回q1。要peek的时候还要更复杂一点,因为q1剩的那个元素不会被poll出去,所以拿到这个元素的值之后还要把这个放到q2,再把q2里的所有元素放回q1,就。。很复杂。。脑子怎么长的呀哇哇哇!!

        错误的输入是:

        ["MyStack","push","push","pop","top"]

        [[],[1],[2],[],[]]

        但是其实我害不知道为啥子错啊,可能还得再想想,报的错是peek() return的null。

class MyStack {
    Queue<Integer> q1;
    Queue<Integer> q2;
    int size;

    public MyStack() {
        q1 = new LinkedList<>();
        q2 = new LinkedList<>();
        size = 0;
    }
    
    public void push(int x) {
        q1.add(x);
        size++;
    }
    
    public int pop() {
        while(size > 1){
            q2.add(q1.poll());
            size--;
        }
        int result = q1.poll();
        while(!q2.isEmpty()){
            q1.add(q2.poll());
            size++;
        }
        return result;
    }
    
    public int top() {
        while(size > 1){
            q2.add(q1.poll());
            size--;
        }
        int result = q1.peek();
        q2.add(q1.poll());
        size--;
        while(!q2.isEmpty()){
            q1.add(q2.poll());
            size++;
        }
        return result;
    }
    
    public boolean empty() {
        return q1.isEmpty();
    }
}

        看了题解才发现原来就是好简单,只需要在添加元素的时候借助队列q2修改一下队列q1让他符合栈后进先出(LIFO)的特点就好了,其他的不管是取栈顶元素值,还是弹出栈顶元素,都直接在q1中的队首元素处进行操作。只用实现push(x)这个方法!!!

        实现细节:新来的元素添加到q2里,这样这个新元素从q2出去的时候一定是第一个出去的,符合了后进先出原则。再把q1里的元素都挪到q2新放进来的元素后面,最后创建一个新的临时队列变量,把q2中的所有元素都转移到q1中去。这样下一次再在q2中加入一个新元素的时候,这个新元素又会成为队首元素,也就是栈中第一个出去的栈顶元素。

        根据这一思路,q1中的全部元素都已经是按照栈的顺序排好的了,从队首取元素,就相当于从栈顶取元素。判断栈是否为空,也只需要判断q1这个队列是否为空就行,q2只是起到一个辅助作用。

class MyStack {
    Queue<Integer> q1;
    Queue<Integer> q2;

    public MyStack() {
        q1 = new LinkedList<Integer>();
        q2 = new LinkedList<Integer>();
    }

    public void push(int x) {
        q2.add(x);
        while (!q1.isEmpty()) {
            q2.add(q1.poll());
        }
        Queue<Integer> temp = q1;
        q1 = q2;
        q2 = temp;
    }

    public int pop() {
        return q1.poll();
    }

    public int top() {
        return q1.peek();
    }

    public boolean empty() {
        return q1.isEmpty();
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值