算法训练营 day11 | 栈与队列part02

150. 逆波兰表达式求值

题目链接

class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        # 如果遇到是数字则直接入栈
        # 如果遇到是操作符,则弹出栈中两个元素使用该操作符进行操作
        res = []
        for i in range(len(tokens)):
            if tokens[i].isdigit() or (tokens[i][0] == '-' and tokens[i][1:].isdigit()): 
                res.append(tokens[i])
            else:
                a = int(res[-1])
                b = int(res[-2])
                res.pop()
                res.pop()
                print(b)
                if tokens[i] == '+':
                    res.append(b + a)
                if tokens[i] == '-':
                    res.append(b - a)
                if tokens[i] == '*':
                    res.append(b * a)
                if tokens[i] == '/':
                    res.append(b / a) 
        return int(res[-1])
总结:如果遇到是数字则直接入栈,如果遇到是操作符,则弹出栈中两个元素使用该操作符进行操作.tokens[i].isdigit()只能识别正数,对于负数需要单独检查。需要注意的是,再进行除法操作时,应该使用“//”整除。我在操作时转换成整数,可能包含隐式转换,所以意外的避免了这个问题。可以进行重写除法操作。这样就可以保证万无一失了。
def div(x, y):
    # 使用整数除法的向零取整方式
    return int(x / y) if x * y > 0 else -(abs(x) // abs(y))

239. 滑动窗口最大值(困难)

题目链接

# from collections importt 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)
    
    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

总结:这题很难,二刷再来看看吧。
思路:维护一个单调队列(保证队列里单调递减或递增的原则)。滑动一个位置,pop一个元素,再push一个元素。如果加入元素比前面元素都大,则弹出前面的元素。每次把窗口内的最大值存起来

347.前 K 个高频元素

题目链接

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        map_ = {}
        for i in range(len(nums)):
            map_[nums[i]] = map_.get(nums[i], 0) + 1

        pri_que = []

        for key, freq in map_.items():
            heapq.heappush(pri_que, (freq, key))
            if len(pri_que) > k:
                heapq.heappop(pri_que)
        
        result = [0] * k
        for i in range(k-1, -1, -1):
            result[i] = heapq.heappop(pri_que)[1]
        return result

总结:有点难,二刷再来看吧。

思路:使用dict记录元素出现的频率,然后使用小顶堆统计前k个最大元素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值