leet code 225.用队列实现栈

问题描述

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

实现 MyStack 类:

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

注意:

你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

解题思路一

虽然题目要求使用二个队列实现一个栈,但我们可以优化一下,只使用一个队列实现一个栈。
对于入栈操作还是对应的队列的入队操作,主要难点在于我们使用队列在取元素时像使用栈一样取出最后放入的元素。我们可以确定的是我们要取出的元素一定是队尾元素,因为栈弹出的元素一定是最后压入的元素。我们可以利用循环将最后一个元素前面的元素依次出队,然后再依次放到队尾,经过的size-1次循环后(size为队列的长度),队列中的最后一个元素位于队首,将其出队返回即可。

代码实现

public class MyStack {

    Queue<Integer> queue = null;


    public MyStack() {
        queue = new ArrayDeque<>();
    }

    public void push(int x) {
        queue.add(x);
    }

    public int pop() {
        int size = queue.size();
        for (int i = 0; i < size-1; i++) {
            queue.add(queue.poll());
        }
        return queue.poll();
    }

    public int top() {
        int size = queue.size();
        for (int i = 0; i < size-1; i++) {
            queue.add(queue.poll());
        }
        int peek = queue.peek();
        queue.add(queue.poll());
        return peek;
    }

    public boolean empty() {
        return queue.size() == 0;
    }


    public static void main(String[] args) {
        MyStack myStack = new MyStack();
        myStack.push(1);
        myStack.push(2);
        System.out.println(myStack.top()); // 返回 2
        System.out.println(myStack.pop()); // 返回 2
        System.out.println(myStack.empty()); // 返回 False
    }
}

实现细节

在使用top方法取出队首元素时,也需要将队列的最后一个元素置于队首,不同的是top()方法仅返回这个值并不会将这个值从队列从取出,所以队列为了还保持原来的顺序还需要将此时的队首元素置到队尾。

解题思路二

依据题目使用二个队列来实现栈操作。第二个队列的作用是了为保存第一个队列出队的临时数据,保存的目的是还需要将第二个队列中的数据重新放回到第一个队列中。

代码实现二

class MyStack2 {

    Queue<Integer> que1 = null;
    Queue<Integer> que2 = null;


    public MyStack2() {
        que1 = new ArrayDeque<>();
        que2 = new ArrayDeque<>();
    }

    public void push(int x) {
        que1.add(x);
    }

    public int pop() {
        int size = que1.size();
        for (int i = 0; i < size-1; i++) {
            que2.add(que1.poll());
        }
        int result = que1.poll();
        for (int i = 0; i < size-1; i++) {
            que1.add(que2.poll());
        }
        return result;
    }

    public int top() {
        int size = que1.size();
        for (int i = 0; i<size-1; i++) {
            que2.add(que1.poll());
        }
        int result = que1.peek();
        que2.add(que1.poll());
        for (int i = 0; i < size; i++) {
            que1.add(que2.poll());
        }
        return result;
    }

    public boolean empty() {
       return que1.size() == 0;
    }

}

实现细节二

push方法是将入栈的数据直接存放到队列中,当我们用pop()取出栈顶元素时,对应着队列的出队操作,需要将最后一个元素之前的元素全部存放到que2中,将que1中仅存的最后一个元素出队后给临时变量result,然后将que2中的数据全部转换到que1 中,最后返回result
在代码实现过程中pop方法中第二个for循环for (int i = 0; i < que2.size()-1; i++)que2.size()的值取随着que1.add(que2.poll());的执行而改变,我们需要有一个变量记录着我们需要循环的次数。size是出队操作之前队列的长度,将que1中的size-1个元素转移到了que2中,que2也需要执行同样次数的循环将que2中的元素存放到que1中。
在top()方法中实现稍有不同是因为top()只查看最后一个元素而不从队列中取出,为了保证队列的顺序将que1中的仅存的一个元素取出存放到que2中,最后将que2中的元素执行size(队列元素个数)次将que2中的元素转换到que1中。

总结

对于用队列实现栈,还是将用栈实现队列,在工程中并没有实际意义,主要考察leetcoder的对数据结构的了解和对算法的实现。

posted @ 2022-11-22 22:24  wzpro  阅读(34)  评论(0)    收藏  举报