This article introduces the problems about stacks and queues in the LeetCode problem set.
232. Implement Queue using Stacks
Problem Description
ideas and code
Initialize two stacks, one named old and the other named new. The specific operation is as follows:
- When adding an element, push it directly into new;
- When popping (output and pop) or output (only output without popping) elements, first judge whether old is empty, if empty, first push the elements in new into new one by one (in the form of a stack), and then pop (or output) The last pushed element in old, otherwise it is directly popped (or output)
code show as below:
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()
running result:
225. Implement Stack using Queues
Problem Description
ideas and code
The author adopts the method of implementing two queues. The main points are as follows:
- Always keep one queue empty and the other non-empty
- When adding an element, first add the new element to the empty queue, and then pop another queue one by one (in the form of a queue) into the queue, and then empty itself
- When popping (or outputting) an element, pop (in a queue) the first element of a non-empty queue
code show as below:
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()
running result:
Referring to the official solution, the author found the method of queue in Python, the code is as follows:
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()
running result:
In the official solution, there is a follow-up solution, that is, only one queue is used to implement the stack:
LeetCode 225 Official Solution
code show as below:
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()
running result:
150. Evaluate Reverse Polish Notation
Problem Description
ideas and code
This question can be realized with the idea of stack.
code show as below:
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()
running result:
71. Simplify Path
Problem Description
ideas and code
This question is implemented through stacks.
code show as below:
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)
running result:
155. Min Stack
Problem Description
ideas and code
If the time complexity is not considered O ( 1 ) O(1)The requirement of O ( 1 ) is very simple to implement, the code is as follows:
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()
running result:
But if consider the time complexity is O ( 1 ) O(1)The requirement of O ( 1 ) requires an additional stack to store the minimum value of the first few elements. When the element is popped up, the stack that stores the minimum value also needs to pop up the element.
code show as below:
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()
running result:
Obviously, adding a stack (list) will increase memory consumption a little.
20. Valid Parentheses
Problem Description
ideas and code
Obviously, this question is also suitable for implementation through stacks.
code show as below:
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
running result: