• 栈与队列3——用队列实现栈


    题目

    题目地址

    力扣地址

    题目说明

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

    实现 MyStack 类:

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

    注意:

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

    示例:

    输入:
    ["MyStack", "push", "push", "top", "pop", "empty"]
    [[], [1], [2], [], [], []]
    输出:
    [null, null, null, 2, 2, false]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    解释:

    MyStack myStack = new MyStack();
    myStack.push(1);
    myStack.push(2);
    myStack.top(); // 返回 2
    myStack.pop(); // 返回 2
    myStack.empty(); // 返回 False
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    提示:

    • 1 ≤ x ≤ 9 1 \leq x \leq 9 1x9
    • 最多调用100 次 push、pop、top 和 empty
    • 每次调用 pop 和 top 都保证栈不为空

    进阶:你能否仅用一个队列来实现栈。

    解题

    方法一:两个队列

    为了满足栈的特性,即最后入栈的元素最先出栈,在使用队列实现栈时,应满足队列前端的元素是最后入栈的元素。可以使用两个队列实现栈的操作,其中 queue 1 \textit{queue}_1 queue1 用于存储栈内的元素, queue 2 \textit{queue}_2 queue2 作为入栈操作的辅助队列。

    入栈操作时,首先将元素入队到 queue 2 \textit{queue}_2 queue2 ,然后将 queue 1 \textit{queue}_1 queue1的全部元素依次出队并入队到 queue 2 \textit{queue}_2 queue2
    ,此时 queue 2 \textit{queue}_2 queue2的前端的元素即为新入栈的元素,再将 queue 1 \textit{queue}_1 queue1 queue 2 \textit{queue}_2 queue2互换,则 queue 1 \textit{queue}_1 queue1的元素即为栈内的元素, queue 1 \textit{queue}_1 queue1的前端和后端分别对应栈顶和栈底。

    由于每次入栈操作都确保 queue 1 \textit{queue}_1 queue1的前端元素为栈顶元,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除 queue 1 \textit{queue}_1 queue1的前端元素并返回即可,获得栈顶元素操作只需要获得 queue 1 \textit{queue}_1 queue1的前端元素并返回即可(不移除元素)。
    由于 queue 1 \textit{queue}_1 queue1用于存储栈内的元素,判断栈是否为空时,只需要判断 queue 1 \textit{queue}_1 queue1是否为空即可。

    在这里插入图片描述
    c++

    class MyStack {
    public:
        queue<int> queue1;
        queue<int> queue2;
    
        /** Initialize your data structure here. */
        MyStack() {
    
        }
    
        /** Push element x onto stack. */
        void push(int x) {
            queue2.push(x);
            while (!queue1.empty()) {
                queue2.push(queue1.front());
                queue1.pop();
            }
            swap(queue1, queue2);
        }
        
        /** Removes the element on top of the stack and returns that element. */
        int pop() {
            int r = queue1.front();
            queue1.pop();
            return r;
        }
        
        /** Get the top element. */
        int top() {
            int r = queue1.front();
            return r;
        }
        
        /** Returns whether the stack is empty. */
        bool empty() {
            return queue1.empty();
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    python3

    class MyStack:
    
        def __init__(self):
            """
            Initialize your data structure here.
            """
            self.queue1 = collections.deque()
            self.queue2 = collections.deque()
    
    
        def push(self, x: int) -> None:
            """
            Push element x onto stack.
            """
            self.queue2.append(x)
            while self.queue1:
                self.queue2.append(self.queue1.popleft())
            self.queue1, self.queue2 = self.queue2, self.queue1
    
    
        def pop(self) -> int:
            """
            Removes the element on top of the stack and returns that element.
            """
            return self.queue1.popleft()
    
    
        def top(self) -> int:
            """
            Get the top element.
            """
            return self.queue1[0]
    
    
        def empty(self) -> bool:
            """
            Returns whether the stack is empty.
            """
            return not self.queue1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    复杂度分析

    • 时间复杂度:入栈操作 O ( n ) O(n) O(n),其余操作都是 O ( 1 ) O(1) O(1),其中 n n n 是栈内的元素个数。
      入栈操作需要将 queue 1 \textit{queue}_1 queue1 中的 n n n 个元素出队,并入队 n + 1 n+1 n+1个元素到 queue 2 \textit{queue}_2 queue2,共有 2 n + 1 2n+1 2n+1次操作,每次出队和入队操作的时间复杂度都是 O ( 1 ) O(1) O(1),因此入栈操作的时间复杂度是 O ( n ) O(n) O(n)
      出栈操作对应将 queue 1 \textit{queue}_1 queue1的前端元素出队,时间复杂度是 O ( 1 ) O(1) O(1)
      获得栈顶元素操作对应获得 queue 1 \textit{queue}_1 queue1的前端元素,时间复杂度是 O ( 1 ) O(1) O(1)
      判断栈是否为空操作只需要判断 queue 1 \textit{queue}_1 queue1 是否为空,时间复杂度是 O ( 1 ) O(1) O(1)

    • 空间复杂度 O ( n ) O(n) O(n),其中 n n n 是栈内的元素个数。需要使用两个队列存储栈内的元素。

    方法二:一个队列

    方法一使用了两个队列实现栈的操作,也可以使用一个队列实现栈的操作。

    使用一个队列时,为了满足栈的特性,即最后入栈的元素最先出栈,同样需要满足队列前端的元素是最后入栈的元素。

    入栈操作时,首先获得入栈前的元素个数 n n n,然后将元素入队到队列,再将队列中的前 n n n 个元素(即除了新入栈的元素之外的全部元素)依次出队并入队到队列,此时队列的前端的元素即为新入栈的元素,且队列的前端和后端分别对应栈顶和栈底。

    由于每次入栈操作都确保队列的前端元素为栈顶元素,因此出栈操作和获得栈顶元素操作都可以简单实现。出栈操作只需要移除队列的前端元素并返回即可,获得栈顶元素操作只需要获得队列的前端元素并返回即可(不移除元素)。

    由于队列用于存储栈内的元素,判断栈是否为空时,只需要判断队列是否为空即可。

    在这里插入图片描述

    c++

    class MyStack {
    public:
        queue<int> q;
    
        /** Initialize your data structure here. */
        MyStack() {
    
        }
    
        /** Push element x onto stack. */
        void push(int x) {
            int n = q.size();
            q.push(x);
            for (int i = 0; i < n; i++) {
                q.push(q.front());
                q.pop();
            }
        }
        
        /** Removes the element on top of the stack and returns that element. */
        int pop() {
            int r = q.front();
            q.pop();
            return r;
        }
        
        /** Get the top element. */
        int top() {
            int r = q.front();
            return r;
        }
        
        /** Returns whether the stack is empty. */
        bool empty() {
            return q.empty();
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    python3

    class MyStack:
    
        def __init__(self):
            """
            Initialize your data structure here.
            """
            self.queue = collections.deque()
    
    
        def push(self, x: int) -> None:
            """
            Push element x onto stack.
            """
            n = len(self.queue)
            self.queue.append(x)
            for _ in range(n):
                self.queue.append(self.queue.popleft())
    
    
        def pop(self) -> int:
            """
            Removes the element on top of the stack and returns that element.
            """
            return self.queue.popleft()
    
    
        def top(self) -> int:
            """
            Get the top element.
            """
            return self.queue[0]
    
    
        def empty(self) -> bool:
            """
            Returns whether the stack is empty.
            """
            return not self.queue
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    复杂度分析

    • 时间复杂度:入栈操作 O ( n ) O(n) O(n),其余操作都是 O ( 1 ) O(1) O(1),其中 n n n 是栈内的元素个数。
      入栈操作需要将队列中的 n n n个元素出队,并入队 n + 1 n+1 n+1个元素到队列,共有 2 n + 1 2n+1 2n+1 次操作,每次出队和入队操作的时间复杂度都是 O ( 1 ) O(1) O(1),因此入栈操作的时间复杂度是 O ( n ) O(n) O(n)
      出栈操作对应将队列的前端元素出队,时间复杂度是 O ( 1 ) O(1) O(1)
      获得栈顶元素操作对应获得队列的前端元素,时间复杂度是 O ( 1 ) O(1) O(1)
      判断栈是否为空操作只需要判断队列是否为空,时间复杂度是 O ( 1 ) O(1) O(1)

    • 空间复杂度: O ( n ) O(n) O(n),其中 nn 是栈内的元素个数。需要使用一个队列存储栈内的元素。

  • 相关阅读:
    思科配置SVI实现VLAN间路由
    聊一下Word2vec-训练优化篇
    [oeasy]python0012_字符_character_chr函数_根据序号得到字符
    如何在JavaScript中比较日期
    Java包
    1074 Reversing Linked List
    【Mongo|1】MongoDB常用命令详细介绍
    CentOS7关闭SELinux
    图Graph的存储、图的广度优先搜索和深度优先搜索(待更新)
    python函数的定义和使用
  • 原文地址:https://blog.csdn.net/wtlll/article/details/126570474