代码随想录 - Day18 - 栈与队列

文章讨论了如何使用栈解决逆波兰表达式求值的问题,以及通过单调队列实现滑动窗口最大值的计算。此外,还介绍了利用哈希映射和堆来找出数组中前K个高频元素的方法。重点在于理解栈、队列以及单调队列的操作规则和在算法中的应用。
摘要由CSDN通过智能技术生成

代码随想录 - 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操作要保持如下规则:
    1. pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
    2. push(value):如果push的元素value大于入口元素的数值,那么就将队列出口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
  • 保持如上规则,每次窗口移动的时候,只要问que.front()就可以返回当前窗口的最大值。

前K个高频元素使用了优先级队列

  • 优先级队列本质是堆
  • 优先级队列对外接口只是从队头取元素,从队尾添加元素,再无其他取元素的方式,看起来就是一个队列
  • 优先级队列内部元素是自动依照元素的权值排列
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值