150. 逆波兰表达式求值
逆波兰表达式(后缀表达式)
- (1+2)x(3+4)的后续表达顺序是: 左右中
- 后缀表达式:12+34+x
使用栈 思路
1. 遇见数字就放入栈,遇见操作运算符,取出栈里的数字进行运算
2. 每次取元素的时候只取两个元素
3. 结果就是栈最后的元素
class Solution(object):
def evalRPN(self, tokens):
"""
:type tokens: List[str]
:rtype: int
"""
# create a stack
stack = []
# iterate the array
for i in range(len(tokens)):
# if we met the operater
if tokens[i] == '+' or tokens[i] == '-' or tokens[i] == '*' or tokens[i] == '/':
# since it's operater, we need prepare number
num1 = stack.pop()
num2 = stack.pop()
# plus
if tokens[i] == '+':
stack.append(int(num2+num1))
# minus
elif tokens[i] == '-':
stack.append(int(num2-num1))
# mul
elif tokens[i] == '*':
stack.append(int(num2*num1))
# div
elif tokens[i] == '/':
# aviod round down, and if it's ngeative number abs first and use negative sign
result = int(num2 / num1) if num2 * num1 > 0 else -(abs(num2) // abs(num1))
stack.append(result)
# if it is number
else:
# put the number into stack
stack.append(int(tokens[i]))
# return answer
return stack[-1]
239. 滑动窗口最大值(一刷理解思路即可)
1. 每滑动一次pop()一个元素,对应的也要push()一个元素
2. 每移动一个位置把遗弃的元素给pop掉,把新加入的元素push进来
3. 每次在get max value查看最大值
单调队列
- 如果队列有比当前元素小的元素,把队列前面全部元素弹出,直到前面的元素没有当前元素小的为止
- 这样就可以维护最大值
- push的规则:
- 如果push进来的元素比前面大,弹出前面的元素,直到前面的元素比当前元素大为止
- 然后获取最大值
- 滑动窗口移动往后移动一位
- 最大值一直是维护在我们队列的出口处
- pop是只有在;出口元素是之前窗口最大值的时候才pop,其他情况push就把不相关的元素弹走了
- 弹出的元素和队列的出口处的元素相同的话
- 说明弹出的元素是当前滑动窗口的最大值
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()
# 如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。
# 这样就保持了单调从大到小,队列口是最大值
def push(self,value):
# 判断是否需要弹出除了我们push的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(object):
def maxSlidingWindow(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
que = MyQueue()
result = []
# 先将前k的元素放进队列
for i in range(k):
que.push(nums[i])
#result记录前k的元素最大值
result.append(que.front())
# 根据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 个高频元素
MAP思路
1. 对元素出现频率进行排序的话使用map
2. key: 是存放我们这里边的元素
3. value: 就是我们元素出现的次数
4. 以value做一个从大到小的排序
5. 输出前k个元素
大顶堆小顶堆 思路
1. 擅长在很大的数据集中求前k个高频或者低频的一个操作
2. 大顶堆: 头部的元素都要比孩子节点的元素大;根节点是最大的元素
3. 小顶堆: 根节点是最小的元素;父亲总是要比左右两个孩子的数值要小
4. 用堆来遍历一遍map里面所有的元素,然后堆里就维持k个元素
5. 使用小顶堆来实现: 每次push进来一个新元素,也要pop一个堆顶的元素
1. 由于小顶堆根节点是最小值,每次push新元素进来都会把最小的给pop出去
2. 遍历完成之后只会有最大的值留在堆里面
import heapq
class Solution(object):
def topKFrequent(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: List[int]
"""
# 统计元素出现的频率
map_ = {} # nums[i] 对应出现的次数
for i in range(len(nums)):
map_[nums[i]] = map_.get(nums[i],0)+1
# 对频率排序
# 定义一个小顶堆,大小为K
pri_que = [] # 小顶堆
# 用固定大小为K的小顶堆,扫描所有频率的数量
for key,freq in map_.items():
heapq.heappush(pri_que,(freq,key))
if len(pri_que) > k:
# 如果堆的大小小于了K,则队列弹出,保证堆的大小一直为k
heapq.heappop(pri_que)
# 找出前K个高频元素,因为小顶堆先弹出是最小的,所以倒叙来输出数组
result = [0] * k
for i in range(k-1,-1,-1):
result[i] = heapq.heappop(pri_que)[1]
return result
标签:150,nums,队列,self,元素,pop,push,347,求值
From: https://blog.csdn.net/NeighborKing/article/details/141483516