算法刷题打卡010 | 队列应用题2道

文章介绍了如何使用单调队列解决LeetCode的239题,滑动窗口最大值,通过维护一个单调递减的队列,实现了O(n)的时间复杂度和O(k)的空间复杂度。另外,对于347题,前K个高频元素,文章提出了使用优先队列结合计数排序的方法,解决了在O(nlogn)的时间复杂度内找到高频元素的问题。
摘要由CSDN通过智能技术生成

LeetCode 239. 滑动窗口最大值

题目链接:239. 滑动窗口最大值 - 力扣(Leetcode)

单调队列经典题目,暴力解法是遍历每个滑动窗口的起始点,然后max求最大值,但以题目的数据量进行很容易超时(max,min本质上也是O(n)的时间复杂度)。窗口移动的效果可以用先入先出的队列来模拟,利用队列的特性构造单调递减的队列,构造的关键是“队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队列里的元素数值是由大到小的。

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        q =collections.deque()
        res = []
        for i in range(len(nums)):
            if not q:
                q.append(nums[i])
                continue
            # i >=  k 收集结果
            if i >= k:
                res.append(q[0])  # 此时的队首是前一个滑动窗口的最大值
                # 当前要把nums[i-k]移出队列,如果队首的最大值正好是nums[i-k],需要popleft
                if q[0] == nums[i-k]:
                    q.popleft()
            # 当前要加入窗口的元素比队尾大时,要将比它小的所有值出队(从右边出)
            while len(q) > 0 and nums[i] > q[-1]:
                q.pop()
            q.append(nums[i])
        res.append(q[0])  # for循环没有收集最后一个窗口的结果
        return res

所有元素最多入队和出队各一次,时间复杂度是O(n),队列中最多同时存储k个值,空间复杂度是O(k)。 

LeetCode 347.前 K 个高频元素

题目链接:347. 前 K 个高频元素 - 力扣(Leetcode)

 首先需要统计每个元素出现的频率,再根据频率排序,这是一般的做法,时间复杂度是O(n+M*logM),其中M为不同元素的个数,最坏情况下M=n;空间复杂度为O(M)。

from queue import PriorityQueue
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        count = collections.Counter(nums)
        # 用大小为k的优先队列
        q = PriorityQueue()  # 默认是最小堆
        for key in count:
            q.put([-count[key], key])  # 按频率取负数排序
        res = []
        # 取前k个
        while k > 0:
            _, key = q.get()
            res.append(key)
            k -= 1
        return res

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值