代码随想录算法训练营第十三天(py)| 239. 滑动窗口最大值、347.前 K 个高频元素

239.滑动窗口最大值

力扣链接
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 。

思路1 暴力遍历

让活动窗口依次移动过去

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        left = 0
        right = left + k
        res = []
        while right <= len(nums):
            res.append(max(nums[left:right]))
            left += 1
            right = left + k
        return res

但是这种方法在输入较大时会超出时间限制。

思路2 单调队列

单调队列,即单调递减或单调递增的队列,python中的单调队列要自己实现。对于此题需要找最大值的情况,利用单调递减队列是合适的。

我们需要一个单调递减队列,放进去窗口里的元素,然后随着窗口的移动,队列也一进一出,每次移动之后,队列告诉我们里面的最大值是什么。
每次窗口移动的时候,调用que.pop,que.push,然后que.front()就返回我们要的最大值。

并且,队列没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了

设计单调队列的时候,pop,和push操作要保持如下规则:

  1. pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
  2. push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止

保持如上规则,每次窗口移动的时候,只要问que.front()就可以返回当前窗口的最大值。

class myqueue:
    def __init__(self):
        self.queue = deque()
    def pop(self, val): # 如果要移出窗口的值就是队列头的值,则直接弹出
        if self.queue and val == self.queue[0]:
            self.queue.popleft()
    def push(self, val): # 如果要push的值大于队列尾的值,则将队列尾的弹出。让push的值成为最小的
        while self.queue and val > self.queue[-1]:
            self.queue.pop()
        self.queue.append(val)
    def front(self):
        return self.queue[0]

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        que = myqueue()
        res = []

        # 先将前k个元素放入que
        for i in range(k):
            que.push(nums[i])
        res.append(que.front())

        for i in range(k, len(nums)):
            que.pop(nums[i-k]) #输入滑动窗口即将移除的元素进行比较
            que.push(nums[i])
            res.append(que.front())
        return res

347.前 K 个高频元素

力扣链接
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

思路 小顶堆

先创建一个哈希表统计每个元素出现的次数,创建一个小顶堆,把哈希表的元素放进去并按照出现次数排序,如果堆长度大于k则将最顶上的元素pop掉,这样留下的就是出现次数最多的元素。

import heapq # 默认小顶堆
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        # 构建字典统计出现次数
        mydict = dict()
        for num in nums:
            if num not in mydict:
                mydict[num] = 1
            else:
                mydict[num] += 1

        # 定义一个大小为k的小顶堆
        pri_que = []
        for key, freq in mydict.items():
            heapq.heappush(pri_que,(freq, key))# 向小顶堆中放置元素,根据freq调整排序
            if len(pri_que)>k:# 如果超过k了,就把堆顶的pop出去
                heapq.heappop(pri_que)
        # print(pri_que)

        result = []
        for i in pri_que:
            result.append(i[1])
        return result
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值