代码随想录|leetcode 239.滑动窗口最大值;347.前k个高频元素

滑动窗口最大值

题目连接 leetcode 239.

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

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

一个简单的思路就是对每一次的窗口进行一次max 运算,然后窗口向右一个个滑动。但是每一次max运算都是 O ( k ) O(k) O(k),那么这样的算法时间复杂度太高了。而且窗口滑动前后,两次max运算中其实是有重复运算的,也就是造成了冗余运算。那么我们该如何保留最大值信息,同时减少时间复杂度呢?
一种想法是运用单调队列。单调队列,顾名思义是元素从大到小或者从小到大排序的队列 (但是队尾可以弹出)。 单调队列的添加元素value,需要把队尾所有小于value的值全部弹出后再添加。
如果把一个数组依次添加到单调队列,则最后的单调队列会是一个由最大值为队头,下降(上升)速度最慢的子数组。
应用到本题中,窗口向右移动一位,队列更新一次,此时的队列的队头即为最大值。窗口左端右移一位,如果删除的这个元素是最大值(等于队头),则队头需弹出;如果不是,说明下一个的最大值仍然相等,且队列不变,因此不需要对队列进行操作。窗口右端右移,将元素添加到单调队列中。

python 代码
from collections import deque
class MyQueue:
    def __init__(self):
        self.que = deque()

    def pop(self,value):
        if self.que[0] == value:
            self.que.popleft()
    
    def push(self,value):
        while self.que and self.que[-1] < value:
            self.que.pop()
        self.que.append(value)

    def front(self):
        return self.que[0]

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        que = MyQueue()
        result = []
        for i in range(k):
            que.push(nums[i])
        result.append(que.front())
        for i in range(k,len(nums)):
            que.pop(nums[i-k])
            que.push(nums[i])
            result.append(que.front())
        return result 

前k个高频元素

题目连接 leetcode 347.

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

思路于 代码随想录

  1. 用字典统计元素及其对应的频数
  2. 用小顶堆维护大小为k的数组
  3. 倒序输出小顶堆
Python 代码
import heapq
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        count = {}
        for i in nums:
            count[i] = count.get(i,0) + 1
        
        pri_que = []

        for (keys,values) in count.items():
            heapq.heappush(pri_que,(values,keys))
            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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值