用栈实现队列
peek只读取不删除, pop读取加删除
class MyQueue:
def __init__(self):
self.stack_in = []
self.stack_out = []
def push(self, x: int) -> None:
self.stack_in.append(x)
def pop(self) -> int:
if self.empty():
return None
if self.stack_out:
return self.stack_out.pop()
else:
for i in range(len(self.stack_in)):
self.stack_out.append(self.stack_in.pop())
return self.stack_out.pop()
def peek(self) -> int:
ans = self.pop()
self.stack_out.append(ans)
return ans
def empty(self) -> bool:
return not (self.stack_in or self.stack_out)
队列实现栈
from collections import deque
class MyStack:
def __init__(self):
"""
Python普通的Queue或SimpleQueue没有类似于peek的功能
也无法用索引访问,在实现top的时候较为困难。
用list可以,但是在使用pop(0)的时候时间复杂度为O(n)
因此这里使用双向队列,我们保证只执行popleft()和append(),因为deque可以用索引访问,可以实现和peek相似的功能
in - 存所有数据
out - 仅在pop的时候会用到
"""
self.queue_in = deque()
self.queue_out = deque()
def push(self, x: int) -> None:
self.queue_in.append(x)
def pop(self) -> int:
"""
1. 首先确认不空
2. 因为队列的特殊性,FIFO,所以我们只有在pop()的时候才会使用queue_out
3. 先把queue_in中的所有元素(除了最后一个),依次出列放进queue_out
4. 交换in和out,此时out里只有一个元素
5. 把out中的pop出来,即是原队列的最后一个
tip:这不能像栈实现队列一样,因为另一个queue也是FIFO,如果执行pop()它不能像
stack一样从另一个pop(),所以干脆in只用来存数据,pop()的时候两个进行交换
"""
if self.empty():
return None
else:
for i in range(len(self.queue_in) - 1):
self.queue_out.append(self.queue_in.popleft())
self.queue_in, self.queue_out = self.queue_out, self.queue_in
return self.queue_out.popleft()
def top(self) -> int:
"""
1. 首先确认不空
2. 我们仅有in会存放数据,所以返回倒数第一个即可
"""
if self.empty():
return None
else:
return self.queue_in[-1]
def empty(self) -> bool:
return len(self.queue_in) == 0
有效括号
方法一:
class Solution:
def isValid(self, s: str) -> bool:
stack = []
for i in s:
if i == '(':
stack.append(')')
elif i == '[':
stack.append(']')
elif i == '{':
stack.append('}')
elif not stack or i != stack[-1]:
return False
else:
stack.pop()
return True if not stack else False
这里用mapping 替代前三步
方法二:
class Solution:
def isValid(self, s: str) -> bool:
stack = []
mapping = {'(': ')', '[': ']', '{': '}'}
for item in s:
if item in mapping.keys():
stack.append(mapping[item])
elif not stack or item != stack[-1]:
return False
else:
stack.pop()
return True if not stack else False
删除字符中所有的相邻重复项
匹配题要先想到栈
方法一:栈
class Solution:
def removeDuplicates(self, s: str) -> str:
res = []
for item in s:
if res and res[-1] == item:
res.pop()
else:
res.append(item)
return "".join(res)
方法二:双指针模拟,如果不让用栈可以作为备选
class Solution:
def removeDuplicates(self, s: str) -> str:
s = list(s)
slow, fast =0, 0
while fast < len(s):
s[slow] = s[fast]
if slow > 0 and s[slow] == s[slow - 1]:
slow -= 1
else:
slow += 1
fast += 1
return ''.join(s[:slow])
逆波兰表达式求值
后缀表达式:用栈,每遇到一个运算符,就把栈里的最后两个取出来运算,取出来的的第一个放后面。
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack = []
for item in tokens:
if item not in {'+', '-', '*', '/'}:
stack.append(item)
else:
first, second = stack.pop(), stack.pop()
ans = int(eval(f'{second} {item} {first}'))
stack.append(ans)
return int(stack.pop())
滑动窗口最大值
class MyQueue: # 单调队列(从大到小)
def __init__(self):
self.queue = []
# 每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。
# 同时pop之前判断队列当前是否为空。
def pop(self, value):
if self.queue and self.queue[0] == value:
self.queue.pop(0)
# 如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。
# 这样就保持了队列里的数值是单调从大到小的了。
def push(self, value):
while self.queue and self.queue[-1] < value:
self.queue.pop()
self.queue.append(value)
# 查询当前队列里的最大值 直接返回队列前端也就是front就可以了。
def front(self):
return self.queue[0]
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
qu = MyQueue()
res = []
for i in range(k): # 先将前k的元素放进队列
qu.push(nums[i]) # result 记录前k的元素的最大值
res.append(qu.front())
for i in range(k, len(nums)):
qu.pop(nums[i - k]) # 滑动窗口移除最前面元素
qu.push(nums[i]) # 滑动窗口前加入最后面的元素
res.append(qu.front()) # 记录对应的最大值
return res
前K个高频元素
import heapq
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
_map = {}
for i in range(len(nums)): # nums[i]:对应出现的次数
_map[nums[i]] = _map.get(nums[i], 0) + 1
# 对频率排序
# 定义一个小顶堆,大小为k
pri_que = []
# 用固定大小为k的小顶堆,扫面所有频率的数值
for item, num in _map.items():
heapq.heappush(pri_que, (num, item))
if len(pri_que) > k: # 如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
heapq.heappop(pri_que)
# 找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
res = [0 for _ in range(k)]
for i in range(k-1, -1, -1):
res[i] = heapq.heappop(pri_que)[1]
return res
感谢阅读