本文介绍 LeetCode 题集中,有关栈和队列的问题。
232. Implement Queue using Stacks(用栈实现队列)
问题描述
思路与代码
初始化两个栈,一个命名为 old,另一个命名为 new。具体操作如下:
- 当新增元素时,直接压入 new 中;
- 当弹出(输出并弹出)或输出(只输出不弹出)元素时,先判断 old 是否为空,如空,先将 new 中元素逐个压入(以栈的方式)new,再弹出(或输出)old 中最后压入的元素,否则直接弹出(或输出)
代码如下:
class MyQueue:
def __init__(self):
self.list_stack_old = []
self.list_stack_new = []
def push(self, x: int) -> None:
self.list_stack_new.append(x) # only need to stock a new value
def pop(self) -> int:
if not self.list_stack_old:
while self.list_stack_new:
self.list_stack_old.append(self.list_stack_new.pop())
return self.list_stack_old.pop() # return the first value and remove it
def peek(self) -> int:
if not self.list_stack_old:
while self.list_stack_new:
self.list_stack_old.append(self.list_stack_new.pop())
return self.list_stack_old[-1] # return the first value but not remove
def empty(self) -> bool:
return not self.list_stack_new and not self.list_stack_old
# 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()
运行效果:
225. Implement Stack using Queues(用队列实现栈)
问题描述
思路与代码
笔者采用的是两个队列实现的方式,要点如下:
- 始终保持一个队列为空,另一个非空
- 新增元素时,先将新元素加入空队列,再将另一个队列逐个(以队列的方式)弹出加入该队列,自身随之清空
- 弹出(或输出)元素时,(以队列的方式)弹出非空队列的第一个元素
代码如下:
class MyStack:
def __init__(self):
self.list_queue_1 = []
self.list_queue_2 = []
def push(self, x: int) -> None:
if not self.list_queue_1:
self.list_queue_1.append(x)
self.list_queue_1 += self.list_queue_2
self.list_queue_2 = []
else:
self.list_queue_2.append(x)
self.list_queue_2 += self.list_queue_1
self.list_queue_1 = []
def pop(self) -> int:
if not self.list_queue_1:
out = self.list_queue_2[0]
self.list_queue_2 = self.list_queue_2[1:]
return out
else:
out = self.list_queue_1[0]
self.list_queue_1 = self.list_queue_1[1:]
return out
def top(self) -> int:
if not self.list_queue_1:
return self.list_queue_2[0]
else:
return self.list_queue_1[0]
def empty(self) -> bool:
return not self.list_queue_1 and not self.list_queue_2
# 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()
运行效果:
参考官方题解,笔者发现 Python 里面自带队列的方法,代码如下:
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
# 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()
运行效果:
在官方题解中,有提供 Follow-up 的解决办法,即只使用一个队列实现栈:
代码如下:
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
# 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()
运行效果:
150. Evaluate Reverse Polish Notation(逆波兰表达式求值)
问题描述
思路与代码
本题用栈的思路实现即可。
代码如下:
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
list_stack = []
set_opr = {'+', '-', '*', '/'}
for c in tokens:
if c in set_opr:
if c == '+':
list_stack.append(list_stack.pop() + list_stack.pop())
elif c == '-':
list_stack.append(-(list_stack.pop() - list_stack.pop()))
elif c == '*':
list_stack.append(list_stack.pop() * list_stack.pop())
else:
a, b = list_stack.pop(), list_stack.pop()
list_stack.append(int(b / a))
else:
list_stack.append(int(c))
return list_stack.pop()
运行效果:
71. Simplify Path(简化路径)
问题描述
思路与代码
本题通过栈来实现。
代码如下:
class Solution:
def simplifyPath(self, path: str) -> str:
list_stack_dir = []
set_skip = {'..', '.', ''} # '' means to skip '//'
for s in path.split('/'):
if s == '..' and list_stack_dir: # if '..', pop to return the higher level
list_stack_dir.pop()
elif s not in set_skip:
list_stack_dir.append(s)
return '/' + '/'.join(list_stack_dir)
运行效果:
155. Min Stack(最小栈)
问题描述
思路与代码
如果不考虑时间复杂度为 O ( 1 ) O(1) O(1) 的要求,实现起来非常简单,代码如下:
class MinStack:
def __init__(self):
self.list_stack = []
def push(self, val: int) -> None:
self.list_stack.append(val)
def pop(self) -> None:
self.list_stack.pop()
def top(self) -> int:
return self.list_stack[-1]
def getMin(self) -> int:
return min(self.list_stack)
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
运行效果:
但如果考虑时间复杂度为 O ( 1 ) O(1) O(1) 的要求,就需要额外增加一个栈,以存储前几个元素的最小值,当弹出元素时,存储最小值的栈同样要弹出元素。
代码如下:
class MinStack:
def __init__(self):
self.list_stack = []
self.list_min = []
def push(self, val: int) -> None:
self.list_stack.append(val)
self.list_min.append(min(self.list_min[-1], val) if self.list_min else val)
def pop(self) -> None:
self.list_stack.pop()
self.list_min.pop()
def top(self) -> int:
return self.list_stack[-1]
def getMin(self) -> int:
return self.list_min[-1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
运行效果:
显然,增加了一个栈(list),就会增加一点内存消耗。
20. Valid Parentheses(有效的括号)
问题描述
思路与代码
显而易见,本题也适合通过栈来实现。
代码如下:
class Solution:
def isValid(self, s: str) -> bool:
list_stack = []
dict_cp = {')': '(', ']': '[', '}': '{'}
for c in s:
if c in dict_cp.keys():
if not list_stack: # in case: no left
return False
elif list_stack.pop() != dict_cp[c]: # in case: not left
return False
else:
list_stack.append(c)
if list_stack: # in case: no enough right
return False
else:
return True
运行效果: