栈和队列
1. 用栈实现队列
LeetCode 232. Implement Queue using Stacks (Easy)
栈和队列是两种顺序完全相反的数据结构。队列先进先出(First In First Out),栈先进后出(First In Last Out)。可以通过使用两个栈,数据在两个栈之间来回“倒腾”,实现队列的功能。
class MyQueue:
def __init__(self):
"""
Initialize your data structure here.
"""
self.stack1 = []
self.stack2 = []
def push(self, x: int) -> None:
"""
Push element x to the back of queue.
"""
while self.stack2:
self.stack1.append(self.stack2.pop())
self.stack1.append(x)
while self.stack1:
self.stack2.append(self.stack1.pop())
def pop(self) -> int:
"""
Removes the element from in front of queue and returns that element.
"""
return self.stack2.pop()
def peek(self) -> int:
"""
Get the front element.
"""
return self.stack2[-1]
def empty(self) -> bool:
"""
Returns whether the queue is empty.
"""
if len(self.stack2) == 0:
return True
else:
return False
# 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()
2. 用队列实现栈
LeetCode 225. Implement Stack using Queues (Easy)
与上面问题实现方法相同。后来的元素进队之前,把队中的元素全部转移到另一个队中,让新来的元素先进队。然后再把数据转移回来。
class MyStack:
def __init__(self):
"""
Initialize your data structure here.
"""
self.queue1 = []
self.queue2 = []
def push(self, x: int) -> None:
"""
Push element x onto stack.
"""
while self.queue2:
self.queue1.append(self.queue2[0])
del self.queue2[0]
self.queue2.append(x)
while self.queue1:
self.queue2.append(self.queue1[0])
del self.queue1[0]
def pop(self) -> int:
"""
Removes the element on top of the stack and returns that element.
"""
ret = self.queue2[0]
del self.queue2[0]
return ret
def top(self) -> int:
"""
Get the top element.
"""
return self.queue2[0]
def empty(self) -> bool:
"""
Returns whether the stack is empty.
"""
if len(self.queue2) == 0:
return True
else:
return False
# 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()
3. 最小值栈
LeetCode 155. Min Stack (Easy)
设置两个栈stack, miniStack,stack用来存储数据,miniStack专门用来存储当前状态的最小值。如果从栈中pop一个数据,那么同时从两个栈里面弹出数据,那么miniStack栈顶依然是当前状态的最小值。Note:如果栈回到空状态,那么min同样也需要初始化到inf的状态,因为历史已经清空了。上一次保存的min失效
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.stack = []
self.miniStack = []
self.min = float('inf')
def push(self, x: int) -> None:
self.stack.append(x)
self.min = min(x, self.min)
self.miniStack.append(self.min)
def pop(self) -> None:
self.stack.pop()
self.miniStack.pop()
# set self.min to inf when the self.miniStack is enmpy. Because when the stack is empty just like the original cases, the min is inf not the history.
self.min = float('inf') if len(self.miniStack) == 0 else self.miniStack[-1]
def top(self) -> int:
return self.stack[-1]
def getMin(self) -> int:
return self.miniStack[-1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
4. 用栈实现括号匹配
LeetCode 20. Valid Parentheses (Easy)
定义left存储左括号,以及组合符号,和一个空栈。遍历字符串,如果当前字符是是左括号,则直接进栈。如果是右括号,那么判断栈的情况,如果是空栈直接返回False,如果不是空栈,则栈顶元素与当前符号进行匹配。如果是成对的,那么弹出栈顶字符,如果不匹配,那么返回错误值。所有字符串遍历完毕,如果栈不空,那么返回False,如果栈空返回True。
class Solution:
def isValid(self, s: str) -> bool:
left = ['(', '{', '[']
combine = ['()', '{}', '[]']
stack = []
for ch in s:
if ch in left:
stack.append(ch)
else:
if len(stack) == 0: return False
if stack[-1] + ch not in combine:
return False
else:
stack.pop()
if len(stack) == 0:
return True
else:
return False
5. 数组中元素与下一个比它大的元素之间的距离
LeetCode 739. Daily Temperatures (Medium)
本题实现方法为单调栈。依然需要明确栈的特性**“先进后出”**是如何在本题中应用的。整个栈从栈顶到栈底数值是递增的。
遍历每日温度,若当日温度大于栈顶索引日的温度,说明当日是栈顶元素的升温日,因此将栈顶元素出栈,计算其与当日的天数差,存放与结果数组中。遍历结束,栈中剩余的元素没有升温日,保持默认值为 0
-
顺序遍历列表元素
-
每个元素下面都进行一次while循环
-
如果栈空,则向栈内压进一个元素;
2.1 如果栈非空,且当前元素比栈顶元素要小,那么向栈内压入该元素(因为没有找到比当前元素大的元素,那么只能将当前元素的信息记录到栈的底面,优先计算后面的元素)
2.2 如果栈非空,且当前元素比栈顶元素要大,那么弹出栈顶元素,并计算栈顶元素与当前元素之间的距离(索引距离)。(意味着栈顶元素已经找到比他大的第一个元素了,该元素就是当前遍历元素
-
遍历结束,如果栈内还有元素,那么意味着,这些元素后面的元素没有找到比他大的值。(由于初始化res为全0列表,因此可以不用考虑这些元素的值)
class Solution:
def dailyTemperatures(self, T: List[int]) -> List[int]:
res = [0 for _ in range(len(T))]
stack = []
for curr_index, curr_temperature in enumerate(T):
while stack and stack[-1][1] < curr_temperature:
top_index = stack.pop()[0]
res[top_index] = curr_index - top_index
stack.append((curr_index, curr_temperature))
return res
6. 循环数组中比当前元素大的下一个元素
LeetCode 503. Next Greater Element II (Medium)
本题与上一题实质是一样的。因为最终返回的数组res大小与传入数组nums是一样的。由于nums是一个环形的,因此将其复制两倍的,同时也计算两倍长度的res,最终返回一半即可。
class Solution:
def nextGreaterElements(self, nums: List[int]) -> List[int]:
res = [-1 for _ in range(2 * len(nums))]
stack = []
new_nums = nums * 2
for curr_index, curr_item in enumerate(new_nums):
while stack and curr_item > stack[-1][1]:
topStack = stack.pop()
res[topStack[0]] = curr_item
stack.append((curr_index, curr_item))
return res[:len(nums)]