leetcode(22)栈和队列系列题目
20. 有效的括号
用字典存匹配的括号
比较栈里第一个元素的值与当前括号
考过两次
class Solution:
def isValid(self, s: str) -> bool:
dic = {'{': '}', '[': ']', '(': ')','?': '?'}
stack = ['?']
for ch in s:
if ch in dic:
stack.append(ch)
elif dic[stack.pop()] != ch:
return False
return len(stack) == 1
622. 设计循环队列
class MyCircularQueue:
def __init__(self, k: int):
self.size = k + 1 # 因为循环队列需要空一个
self.front = 0
self.rear = 0
# self.queue = [0] * (k + 1)
self.queue = [0 for _ in range(k+1)]
def enQueue(self, value: int) -> bool:
if self.isFull():
return False
else:
self.rear = (self.rear + 1) % self.size
self.queue[self.rear] = value
return True
def deQueue(self) -> bool:
if self.isEmpty():
return False
else:
self.front = (self.front + 1) % self.size
return True
def Front(self) -> int:
"""返回头部所指的元素:注意是下一个,因为有一个一直空着"""
if self.isEmpty():
return -1
else:
return self.queue[(self.front + 1) % self.size]
def Rear(self) -> int:
if self.isEmpty():
return -1
else:
return self.queue[self.rear]
def isEmpty(self) -> bool:
return self.front == self.rear
def isFull(self) -> bool:
"""判断队满:注意队满的是队首和队尾之间空着一个"""
return self.front == (self.rear + 1) % self.size
641. 设计循环双端队列
- 初始化容量size = k + 1,并建立大小为size的数组deque;还需要两个指针front和rear,front指向数组中第一个数据位置,rear指向数组中下一个可存储的空位置。也是因为rear总是指向空位置,所以之前初始化容量的时候多加了一个1
- 判空条件:front == rear
判满条件:(rear + 1) % capacity == front
也就是rear再后移一位就碰到了front,因为是循环存储的,所以rear + 1可能会比capacity大,取模之后再和front比较 - 需要注意代码中对rear和front的所有 + 1 或 - 1 操作都需要取模,因为都可能超出数组下标范围,并且 - 1 操作因为还可能导致产生负数,还需要再加一个size避免产生负数。比如front = (front - 1 + size) % size
class MyCircularDeque:
def __init__(self, k: int):
self.size = k + 1
self.front = 0
self.rear = 0
self.queue = [0] * (k + 1)
def insertFront(self, value: int) -> bool:
if self.isFull():
return False
else:
self.front = (self.front - 1 + self.size) % self.size ##
self.queue[self.front] = value
return True
def insertLast(self, value: int) -> bool:
if self.isFull():
return False
else:
self.queue[self.rear] = value # 注意先赋值再移动rear的位置
self.rear = (self.rear + 1) % self.size ##
return True
def deleteFront(self) -> bool:
if self.isEmpty():
return False
else:
self.front = (self.front + 1) % self.size
return True
def deleteLast(self) -> bool:
if self.isEmpty():
return False
else:
self.rear = (self.rear - 1 + self.size) % self.size ##
return True
def getFront(self) -> int:
if self.isEmpty():
return -1
else:
return self.queue[self.front]
def getRear(self) -> int:
if self.isEmpty():
return -1
else:
return self.queue[(self.rear - 1 + self.size) % self.size] ##
def isEmpty(self) -> bool:
return self.front == self.rear
def isFull(self) -> bool:
return self.front == (self.rear + 1) % self.size
1670. 设计前中后队列
class FrontMiddleBackQueue:
def __init__(self):
self.q = []
def pushFront(self, val: int) -> None:
self.q.insert(0, val)
def pushMiddle(self, val: int) -> None:
self.q.insert(len(self.q) // 2, val)
def pushBack(self, val: int) -> None:
self.q.append(val)
def popFront(self) -> int:
if self.q:
return self.q.pop(0)
return -1
def popMiddle(self) -> int:
if self.q:
return self.q.pop((len(self.q) - 1) // 2) # 注意-1
return -1
def popBack(self) -> int:
if self.q:
return self.q.pop(-1)
return -1
933. 最近的请求次数
t代表这个员工的工号,每次新员工t加入q公司前先把工号小于t -3000的老家伙都辞退,然后再让t入职,统计q公司现有几个员工
class RecentCounter:
def __init__(self):
self.queue = deque()
def ping(self, t: int) -> int:
self.queue.append(t)
while self.queue and t - 3000 > self.queue[0]:
self.queue.popleft()
return len(self.queue)
面试题 17.09. 第 k 个数
class Solution:
def getKthMagicNumber(self, k: int) -> int:
# 使用小顶堆处理(因为每次需要得到最小的数字)
heap = [1] # 第一个元素是1
for _ in range(k):
res = heapq.heappop(heap) # 每次取出堆中的首元素(最小元素)
while heap and res == heap[0]: # 去除重复元素
heapq.heappop(heap)
heapq.heappush(heap, res * 3) # 依次将当前元素乘以3,5,7的值压入堆中
heapq.heappush(heap, res * 5)
heapq.heappush(heap, res * 7)
return res
1106. 解析布尔表达式
从左到右遍历表达式 expression,对于遍历到的每个字符 cc:
如果 e 是 "tf!&|" 中的一个,直接将其入栈;
如果 e 是右括号 ')',将栈中元素依次出栈,直到遇到操作符 '!' 或 '&' 或 '|'。过程中用变量 t 和 f 记录出栈字符中 't' 和 'f' 的个数。最后根据出栈字符的个数和操作符计算得到新的字符 't' 或 'f',并将其入栈。
遍历完表达式 expression 后,栈中只剩下一个字符,如果是 't',返回 true,否则返回 false。
class Solution:
def parseBoolExpr(self, expression: str) -> bool:
stk = []
for e in expression:
if e in 'tf!&|':
stk.append(e)
elif e == ')':
t = f = 0
while stk[-1] in 'tf':
t += stk[-1] == 't'
f += stk[-1] == 'f'
stk.pop()
match stk.pop():
case '!':
c = 'f' if t else 't'
case '&':
c = 'f' if f else 't'
case '|' :
c = 't' if t else 'f'
stk.append(c)
return stk[0] == 't'
155. 最小栈
使用辅助栈
class MinStack:
def __init__(self):
self.st = []
self.min_st = []
def push(self, val: int) -> None:
self.st.append(val)
if not self.min_st or val <= self.min_st[-1]:
self.min_st.append(val)
def pop(self) -> None:
if self.st.pop() == self.min_st[-1]:
self.min_st.pop()
def top(self) -> int:
return self.st[-1]
def getMin(self) -> int:
return self.min_st[-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()
895. 最大频率栈
自己的写法:
class FreqStack:
def __init__(self):
self.stack = []
self.cnt = defaultdict(int)
def push(self, val: int) -> None:
self.stack.append(val)
self.cnt[val] += 1
def pop(self) -> int:
most_freq = max(self.cnt.values())
for i in range(len(self.stack) - 1, -1, -1):
if self.cnt[self.stack[i]] == most_freq:
res = self.stack[i]
self.cnt[self.stack[i]] -= 1
self.stack.pop(i)
return res
# Your FreqStack object will be instantiated and called as such:
# obj = FreqStack()
# obj.push(val)
# param_2 = obj.pop()
优化后的方法:哈希表 + 优先队列(大根堆)O(logn)
class FreqStack:
def __init__(self):
self.q = []
self.cnt = defaultdict(int)
self.ts = 0
def push(self, val: int) -> None:
self.ts += 1
self.cnt[val] += 1
# 记录每次压入栈中的次数和索引,默认栈顶是最小值,因此取反
heappush(self.q, (-self.cnt[val], -self.ts, val))
def pop(self) -> int:
res = heappop(self.q)[2]
self.cnt[res] -= 1
return res
# Your FreqStack object will be instantiated and called as such:
# obj = FreqStack()
# obj.push(val)
# param_2 = obj.pop()
进一步优化:双哈希表 O(1)
class FreqStack:
def __init__(self):
self.fre = defaultdict(list)
self.cnt = defaultdict(int)
self.mx = 0
def push(self, val: int) -> None:
self.cnt[val] += 1 # 记录元素出现的频率
self.fre[self.cnt[val]].append(val) # 记录该频率的元素
self.mx = max(self.mx, self.cnt[val])
def pop(self) -> int:
res = self.fre[self.mx].pop()
self.cnt[res] -= 1
if not self.fre[self.mx]:
self.mx -= 1
return res
# Your FreqStack object will be instantiated and called as such:
# obj = FreqStack()
# obj.push(val)
# param_2 = obj.pop()
分类:
leetcode算法题
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示