【Leetcode笔记】前K个高频元素

Leetcode原题链接:前K个高频元素

一、思路

  • 统计每个数字出现次数,存入字典。
  • 维护以次数为准的大小为k的小顶堆,每次push新数后,因为要维护小顶堆大小为k,因此pop出堆顶元素(最小)。

二、代码

1、小顶堆思想代码

(没写出来,看看高手代码)

#时间复杂度:O(nlogk)
#空间复杂度:O(n)
import heapq
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        #要统计元素出现频率
        map_ = {} #nums[i]:对应出现的次数
        for i in range(len(nums)):
            map_[nums[i]] = map_.get(nums[i], 0) + 1
        
        #对频率排序
        #定义一个小顶堆,大小为k
        pri_que = [] #小顶堆
        
        #用固定大小为k的小顶堆,扫描所有频率的数值
        for key, freq in map_.items():
            heapq.heappush(pri_que, (freq, key))
            if len(pri_que) > k: #如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
                heapq.heappop(pri_que)
        
        #找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
        result = [0] * k
        for i in range(k-1, -1, -1):
            result[i] = heapq.heappop(pri_que)[1]
        return result

其实最后没要求从高到低排序,所以倒也不用倒序。

2、另一个看起来比较简单的代码

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        # 先计次
        n = len(nums)
        dic = {}
        for i in range(n):
            if nums[i] not in dic:
                dic[nums[i]] = 1
            else:
                dic[nums[i]] += 1
        
        # 每次弹出一个最大,弹k次
        res = []
        while k > 0:
            tmp = 0
            for num in dic:
                if dic[num] > tmp:
                    tmp = dic[num]
                    cur = num
            dic[cur] = -1
            res.append(cur)
            k -= 1
        return res

这段代码的时间复杂度为O(klogn),满足题意。
其中,计次的时间复杂度为O(n),弹出最大的元素的时间复杂度为O(logn)。因为这个操作被执行了k次,所以总时间复杂度为O(klogn)。

三、总结

  • 没用过heapq库,这里做个简单介绍:

heapq是Python的一个内置库,它提供了堆队列算法的实现。堆是一种特殊的数据结构,它是一棵树,其中每个父节点的值都小于或等于其子节点的值。在Python中,堆通常使用列表来实现。
heapq库提供了许多有用的函数,包括:
heappush:将一个元素推入堆中。
heappop:从堆中弹出最小的元素。
heapify:将列表转换为堆。
heapreplace:弹出最小的元素并将新元素推入堆中。
以下是一个使用heapq库的示例:

import heapq
my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]
heapq.heapify(my_list)
print(my_list)  # 输出 [1, 1, 2, 3, 3, 9, 4, 6, 5, 5, 5]

这个例子将一个列表转换为堆,并打印出结果。

  • 方法2把k逐次减小,每次弹出最大值,非常直观,之前一直觉得题目给的参数不能修改,也算是思想被禁锢了。

部分内容参考代码随想录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值