📜  数据结构 |堆 |问题 8(1)

📅  最后修改于: 2023-12-03 15:26:08.964000             🧑  作者: Mango

数据结构 | 堆 | 问题 8

问题描述

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

解决方案

使用堆(优先队列)来解决这个问题,堆可以把时间复杂度降到 O(nlogk)。

具体实现如下:

  1. 遍历数组,使用哈希表(字典)统计每个元素的出现次数,并记录最大出现次数 max_freq。

  2. 定义一个最小堆,把元素和它对应的出现次数放到堆里面,堆的大小为 k。

  3. 遍历哈希表,对于每个元素,如果出现次数大于最小堆堆顶的元素的出现次数,就把堆顶元素弹出,把当前元素和它的出现次数加入堆中。

  4. 最后,输出堆中的 k 个元素即可。

代码实现如下所示:

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        # 哈希表统计每个元素的出现次数
        freq_dict = {}
        max_freq = 0
        for num in nums:
            freq_dict[num] = freq_dict.get(num, 0) + 1
            max_freq = max(max_freq, freq_dict[num])
        
        # 定义一个最小堆,堆中元素是 (出现次数, 元素) 的元组
        heap = []
        for num, freq in freq_dict.items():
            # 把元素和对应的出现次数放入堆中
            heapq.heappush(heap, (freq, num))
            # 如果堆的大小超过了 k,就弹出堆顶元素(出现次数最小的元素)
            if len(heap) > k:
                heapq.heappop(heap)
        
        # 输出堆中的 k 个元素,注意堆中元素的顺序是相反的,因此要反转一下
        return [x[1] for x in reversed(heap)]
时间复杂度

遍历数组需要 O(n) 的时间,遍历哈希表需要 O(n) 的时间,向堆中插入元素和弹出堆顶元素需要 O(logk) 的时间,因此总时间复杂度是 O(nlogk)。

空间复杂度

哈希表的大小为 O(n),堆的大小为 O(k),因此空间复杂度是 O(n+k)。

总结

这道题目考察了对堆(优先队列)的理解和使用。堆可以帮助我们快速在一组元素中找到最大或最小的元素,它的时间复杂度为 O(logn)。在解决这个问题时,我们通过把元素和它的出现次数放到堆中,并限制堆的大小为 k,来找到出现频率前 k 高的元素,时间复杂度为 O(nlogk)。