题目 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()
复杂度:
-
push(int x)
:时间复杂度是 O(1),因为只涉及向stack_in
中添加一个元素。 -
pop()
和peek()
:在最坏情况下,时间复杂度是 O(n),其中 n 是stack_in
中的元素数量。这是因为可能需要将所有的元素从stack_in
移动到stack_out
。然而,实际上这种最坏情况发生的频率很低,因为只有当stack_out
为空的时候才需要这么做。因此,如果你将这个操作的时间均摊(amortize)在所有的元素上,那么pop()
和peek()
的均摊时间复杂度是 O(1)。 -
empty()
:时间复杂度是 O(1),因为只涉及检查stack_in
和stack_out
是否都为空。
在空间复杂度方面,对于包含 n 个元素的队列,空间复杂度是 O(n)。这是因为所有的元素都存储在 stack_in
和 stack_out
中,即使有些元素在一段时间内可能会从 stack_in
移动到 stack_out
,但总的元素数量不变。
题目 225.用队列实现栈
题目描述:
使用栈实现队列的下列操作:
push(x) -- 将一个元素放入队列的尾部。
pop() -- 从队列首部移除元素。
peek() -- 返回队列首部的元素。
empty() -- 返回队列是否为空。
解题思路:
-
push(int x)
:我们总是将新元素加入 queue1。 -
pop()
:由于栈是后进先出的结构,我们需要移除最后加入的元素。为了得到这个元素,我们首先将除最后一个元素以外的所有元素移动到 queue2,然后移除并返回 queue1 中的最后一个元素。然后,我们将 queue1 和 queue2 交换,以便下次 push 操作可以继续在 queue1 上执行。 -
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
-
top()
:这个操作和 pop 类似,但我们不会移除栈顶元素。所以在获取到 queue1 中最后一个元素后,我们需要将它再次加入到 queue2。 -
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)