Day09 算法学习| 队列和栈互相实现

题目 232.用栈实现队列

题目描述:

使用只有两个栈实现一个先入先出 (FIFO) 的队列。实现的队列应支持正常队列的所有功能 (push,peek,pop 和 empty)。

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾。

int pop() 从队列前端移除元素并返回。

int peek() 返回队列前端的元素。

boolean empty() 如果队列为空则返回真,否则返回假。

解题思路:

stack_out:进栈

stack_in:出栈

1.void push(int x) 将元素 x 推到队列的末尾:

运用python中的list.append()功能

2.int pop() 从队列前端移除元素并返回:

先检查stack_out是不是空的,是空的再一个一个倒序添加stack_in中的元素即为 stack_in中的list.pop(), 最后再返回stack_out中的最后一个元素,即为stack_in的第一个,stack_out.pop()

3. nt peek() 返回队列前端的元素。

和2的区别就是不移除前段元素,所以返回stack_out【-1】

4. boolean empty() 如果队列为空则返回真,否则返回假。

只有当

stack_out 和 stack_in 都为空的时候队列才会为空

在 Python 中,"self" 是一个约定俗成的名称,用于指代实例本身。当你定义一个类的方法时,它的第一个参数需要是 "self"。这个 "self" 参数为方法提供了对实例自身的引用,这样你就可以访问和修改实例的属性。

在你的代码中,"self.stack_in" 和 "self.stack_out" 分别表示 "MyQueue" 实例的 "stack_in" 属性和 "stack_out" 属性。当你在方法中使用 "self.stack_in" 或 "self.stack_out" 时,你实际上是在访问或修改这个 "MyQueue" 实例的 "stack_in" 或 "stack_out" 属性。

没有 "self" 的话,"stack_in" 和 "stack_out" 就会被视为方法的局部变量,而不是实例的属性。当方法结束时,局部变量就会被销毁,而实例的属性则会一直存在,直到实例被销毁。因此,为了在不同的方法之间共享和保留 "stack_in" 和 "stack_out",你需要使用 "self.stack_in" 和 "self.stack_out"。

代码:

class MyQueue:

    def __init__(self):
        self.stack_in=[]
        self.stack_out=[]
        
#Pushes element x to the back of the queue.
#在队列末尾添加一个元素
    def push(self, x: int) -> None:
        self.stack_in.append(x)
        
#remove item from the first element and return it
#移除第一个元素并返回
    def pop(self) -> int:
        if not self.stack_out:
            while self.stack_in:
                self.stack_out.append(self.stack_in.pop())
        return self.stack_out.pop() if self.stack_out else None

        
#Returns the element at the front of the queue.
#返回第一个元素,不移除
    def peek(self) -> int:
        if not self.stack_out:
            while self.stack_in:
                self.stack_out.append(self.stack_in.pop())
        return self.stack_out[-1] if self.stack_out else None

#Returns true if the queue is empty, false otherwise.
    def empty(self) -> bool:
        """
        只要in或者out有元素,说明队列不为空
        """
        return len(self.stack_in) == 0 and len(self.stack_out) == 0


# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

复杂度:

  1. push(int x):时间复杂度是 O(1),因为只涉及向 stack_in 中添加一个元素。

  2. pop()peek():在最坏情况下,时间复杂度是 O(n),其中 n 是 stack_in 中的元素数量。这是因为可能需要将所有的元素从 stack_in 移动到 stack_out。然而,实际上这种最坏情况发生的频率很低,因为只有当 stack_out 为空的时候才需要这么做。因此,如果你将这个操作的时间均摊(amortize)在所有的元素上,那么 pop()peek() 的均摊时间复杂度是 O(1)。

  3. empty():时间复杂度是 O(1),因为只涉及检查 stack_instack_out 是否都为空。

在空间复杂度方面,对于包含 n 个元素的队列,空间复杂度是 O(n)。这是因为所有的元素都存储在 stack_instack_out 中,即使有些元素在一段时间内可能会从 stack_in 移动到 stack_out,但总的元素数量不变。

题目 225.用队列实现栈

题目链接

题目描述:

使用栈实现队列的下列操作:

push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。

解题思路:

  1. push(int x):我们总是将新元素加入 queue1。

  2. pop():由于栈是后进先出的结构,我们需要移除最后加入的元素。为了得到这个元素,我们首先将除最后一个元素以外的所有元素移动到 queue2,然后移除并返回 queue1 中的最后一个元素。然后,我们将 queue1 和 queue2 交换,以便下次 push 操作可以继续在 queue1 上执行。 

  3.     def pop(self) -> int:
            """
            Removes the element on top of the stack and returns that element.
            """
            while len(self.queue1) > 1:
                self.queue2.append(self.queue1.pop(0))
            ret = self.queue1.pop(0)
            self.queue1, self.queue2 = self.queue2, self.queue1
            return ret

  4. top():这个操作和 pop 类似,但我们不会移除栈顶元素。所以在获取到 queue1 中最后一个元素后,我们需要将它再次加入到 queue2。

  5. empty():我们只需要检查 queue1 是否为空就可以了。

代码:

与用栈实现队列的区别:

在用栈实现队列时,我们也需要两个栈。新元素总是加入到 stack1,而 stack2 用于存放准备出队列的元素。在每次 pop 或 peek 操作时,如果 stack2 为空,我们就需要先将 stack1 的所有元素逆序移动到 stack2。

相比之下,用队列实现栈时,所有的新元素都是直接加入到 queue1,而在 pop 或 top 操作时,我们总是将除最后一个元素以外的所有元素移动到 queue2,然后返回 queue1 的最后一个元素。

class MyStack:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.queue1=[]
        self.queue2=[]
        
#Pushes element x to the top of the stack.
# 元素 x 入栈
    def push(self, x: int) -> None:
        """
        Push element x onto stack.
        """
        self.queue1.append(x)

#Removes the element on the top of the stack and returns it.
#移除栈顶元素
    def pop(self) -> int:
        """
        Removes the element on top of the stack and returns that element.
        """
        while len(self.queue1) > 1:
            self.queue2.append(self.queue1.pop(0))
        ret = self.queue1.pop(0)
        self.queue1, self.queue2 = self.queue2, self.queue1
        return ret

#Returns the element on the top of the stack.
#获取栈顶元素
    def top(self) -> int:
        """
        Get the top element.
        """
        while len(self.queue1) > 1:
            self.queue2.append(self.queue1.pop(0))
        ret = self.queue1[0]
        self.queue2.append(self.queue1.pop(0))
        self.queue1, self.queue2 = self.queue2, self.queue1
        return ret

# Returns true if the stack is empty, false otherwise.
#返回栈是否为空
    def empty(self) -> bool:
        """
        Returns whether the stack is empty.
        """
        return not self.queue1

        


# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()

复杂度:

  • push() 操作的时间复杂度:O(1)
  • pop() 操作的时间复杂度:O(n)
  • top() 操作的时间复杂度:O(n)
  • empty() 操作的时间复杂度:O(1)
  • 空间复杂度:O(n)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值