其他分享
首页 > 其他分享> > 【排序】力扣347:前K个高频元素(未完)

【排序】力扣347:前K个高频元素(未完)

作者:互联网

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

示例:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

进阶:你所设计算法的时间复杂度 必须 优于 O(nlogn) ,其中 n 是数组大小。

3种方法:部分快排思想;直接排序;优先队列

方法1:最小堆

  1. 借助【哈希表】来建立数字和其出现次数的映射,遍历一遍数组统计元素的频率
  2. 维护一个元素数目为 k 的最小堆
  3. 每次都将新的元素与堆顶元素(堆中频率最小的元素)进行比较
  4. 如果新的元素的频率比堆顶端的元素大,则弹出堆顶端的元素,将新的元素添加进堆中
  5. 最终,堆中的 k 个元素即为前 k 个高频元素

作者:cxywushixiong
链接:https://leetcode-cn.com/problems/top-k-frequent-elements/solution/leetcode-di-347-hao-wen-ti-qian-k-ge-gao-pin-yuan-/

时间复杂度:O(nlogk),n 表示数组的长度。首先,遍历一遍数组统计元素的频率,这一系列操作的时间复杂度是O(n);接着,遍历用于存储元素频率的 map,如果元素的频率大于最小堆中顶部的元素,则将顶部的元素删除并将该元素加入堆中,这里维护堆的数目是 k,所以这一系列操作的时间复杂度是 O(nlogk) 的;因此,总的时间复杂度是 O(nlog⁡k)。
空间复杂度:O(n),最坏情况下(每个元素都不同),map 需要存储 n 个键值对,优先队列需要存储 k 个元素,因此,空间复杂度是 O(n)。

方法2:桶排序
设置若干个桶,每个桶存储出现频率相同的数。桶的下标表示数出现的频率,即第 i 个桶中存储的数出现的频率为 i。
把数都放到桶之后,从后向前遍历桶,最先得到的 k 个数就是出现频率最多的的 k 个数。

首先依旧使用哈希表统计频率,统计完成后,创建一个数组,将频率作为数组下标,对于出现频率不同的数字集合,存入对应的数组下标即可。


时间复杂度:O(n),n 表示数组的长度。首先,遍历一遍数组统计元素的频率,这一系列操作的时间复杂度是 O(n);桶的数量为 n+1,所以桶排序的时间复杂度为 O(n);因此,总的时间复杂度是 O(n)。
空间复杂度:很明显为 O(n)。

方法3:python的Counter()
统计每个数的频率,输出最大的几个,这完全迎合了Python中的Counter类,调用其的几个方法即可。

Counter 是一个在collections包里的类,正如其名,是一个用于计数的工具。
我们可以用Counter(nums)这样的构造函数构造一个Counter类,其中nums是一个列表。
构造好的Counter实例可以看作一个字典,键是nums的每一项,值是它的出现次数。
如果上面的叙述让你感到很混乱的话,我不妨举个例子。
如果一个列表a = [1,1,3,4,3],你想要统计每项的出现次数,那么你使用b = Counter(a),那么这时候b就像一个这样的字典{1:2,3:2,4:1},表示数字1出现了2次,数字3出现了2次,数字4出现了1次。
可是题目里要我们输出的是最多的K项,这时候可以应用Counter的一个函数,most_common(k),这个函数就是返回最多出现的K项
但是返回的形式是一个元祖列表,类似[(1,2),(3,2),(4,1)]的形式,我们只需要键也就是第一项,所以要使用列表生成式处理一下即可。

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        from collections import Counter
        return [i[0] for i in Counter(nums).most_common(k)]

作者:qsctech-sange
链接:https://leetcode-cn.com/problems/top-k-frequent-elements/solution/yi-xing-python3dai-ni-zou-jin-counterlei-by-jimmy0/

标签:Counter,数组,nums,复杂度,元素,力扣,347,频率,排序
来源: https://www.cnblogs.com/Jojo-L/p/16100394.html