代码随想录 - Day18 - 栈与队列
150. 逆波兰表达式求值
写的代码有些复杂,但比较直观,一看就懂
stack = []
for i in tokens:
long = len(stack) - 1
if i == "+":
a = stack[long - 1] + stack[long]
stack.pop()
stack.pop()
stack.append(a)
elif i == "-":
a = stack[long - 1] - stack[long]
stack.pop()
stack.pop()
stack.append(a)
elif i == "*":
a = stack[long - 1] * stack[long]
stack.pop()
stack.pop()
stack.append(a)
elif i == "/":
a = int(stack[long - 1] / stack[long])
stack.pop()
stack.pop()
stack.append(a)
else:
stack.append(int(i))
return stack[0]
看到的别人写的更简短的代码:
第一种:
op_map = {'+': add, '-': sub, '*': mul, '/': lambda x, y: int(x / y)}
def evalRPN(self, tokens: List[str]) -> int:
stack = []
for token in tokens:
if token not in {'+', '-', '*', '/'}:
stack.append(int(token))
else:
op2 = stack.pop()
op1 = stack.pop()
stack.append(self.op_map[token](op1, op2)) # 第一个出来的在运算符后面
return stack.pop()
第二种:
stack = []
for item in tokens:
if item not in {"+", "-", "*", "/"}:
stack.append(item)
else:
first_num, second_num = stack.pop(), stack.pop()
stack.append(
int(eval(f'{second_num} {item} {first_num}')) # 第一个出来的在运算符后面
)
return int(stack.pop()) # 如果一开始只有一个数,那么会是字符串形式的
239. 滑动窗口最大值
想了三种办法都超时了,看了一下题解,思路理解了,但写不出
学习别人的代码:
from collections import deque
class MyQueue: #单调队列(从大到小
def __init__(self):
self.queue = deque() #这里需要使用deque实现单调队列,直接使用list会超时
#每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。
#同时pop之前判断队列当前是否为空。
def pop(self, value):
if self.queue and value == self.queue[0]:
self.queue.popleft()#list.pop()时间复杂度为O(n),这里需要使用collections.deque()
#如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。
#这样就保持了队列里的数值是单调从大到小的了。
def push(self, value):
while self.queue and value > self.queue[-1]:
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]:
que = MyQueue()
result = []
for i in range(k): #先将前k的元素放进队列
que.push(nums[i])
result.append(que.front()) #result 记录前k的元素的最大值
for i in range(k, len(nums)):
que.pop(nums[i - k]) #滑动窗口移除最前面元素
que.push(nums[i]) #滑动窗口前加入最后面的元素
result.append(que.front()) #记录对应的最大值
return result
347. 前 K 个高频元素
hashmap = {}
for i in range(len(nums)): # 用字典存key和value,其中key为元素,value为该元素出现的次数
hashmap[nums[i]] = 1 + hashmap.get(nums[i], 0) # 若map里没有该key则新添加key和value;若存在key则给相应value增加1
hashmap = sorted(hashmap.items(), key=lambda d:d[1], reverse = True) # 给字典进行排序
res = []
for i in range(0, k):
res.append(hashmap[i][0]) # 将前k个key存到result列表里
return res
总结
求滑动窗口最大值使用到了单调队列
- 设计单调队列的时候,pop,和push操作要保持如下规则:
- pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
- push(value):如果push的元素value大于入口元素的数值,那么就将队列出口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
- 保持如上规则,每次窗口移动的时候,只要问que.front()就可以返回当前窗口的最大值。
前K个高频元素使用了优先级队列
- 优先级队列本质是堆
- 优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列
- 优先级队列内部元素是自动依照元素的权值排列