前 K 个高频元素-堆

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

示例 1:

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

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

提示:

1 <= nums.length <= 1 0 5 10^5 105
k 的取值范围是 [1, 数组中不相同的元素的个数]
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

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

import collections
import heapq
class Solution:
    def topKFrequent(self, nums: list, k: int) -> list:
        tmp = {}
        for n in nums:
            if n in tmp:
                tmp[n] += 1
            else:
                tmp[n] = 1

        tmp = sorted(tmp.items(), key=lambda x: x[1], reverse=True)

        return [tmp[i][0] for i in range(k)]
	
    #使用小顶堆,重点解法
    def topKFrequent(self, nums: list, k: int) -> list:
        freqs = collections.Counter(nums)
        heap = []
        for key, val in freqs.items():
            heapq.heappush(heap, [val, key])
            if len(heap) > k:
                heapq.heappop(heap)
        return [v for k, v in heap]


if __name__ == '__main__':
    s = Solution()
    print(s.topKFrequent([1,1,1,2,2,3], 2))
    print(s.topKFrequent([1], 1))

首先遍历整个数组,并使用哈希表记录每个数字出现的次数,并形成一个「出现次数数组」。找出原数组的前 k 个高频元素,就相当于找出「出现次数数组」的前 k 大的值。

最简单的做法是给「出现次数数组」排序。但由于可能有 O ( N ) O(N) O(N) 个不同的出现次数(其中 N 为原数组长度),故总的算法复杂度会达到 O ( N log ⁡ N ) O(N\log N) O(NlogN),不满足题目的要求。

在这里,我们可以利用堆的思想:建立一个小顶堆,然后遍历「出现次数数组」:

  • 如果堆的元素个数小于 k,就可以直接插入堆中。
  • 如果堆的元素个数等于 k,则检查堆顶与当前出现次数的大小。如果堆顶更大,说明至少有 k 个数字的出现次数比当前值大,故舍弃当前值;否则,就弹出堆顶,并将当前值插入堆中。

遍历完成后,堆中的元素就代表了「出现次数数组」中前 k 大的值。

复杂度分析

时间复杂度: O ( N log ⁡ k ) O(N\log k) O(Nlogk),其中 N 为数组的长度。我们首先遍历原数组,并使用哈希表记录出现次数,每个元素需要 O ( 1 ) O(1) O(1) 的时间,共需 O ( N ) O(N) O(N) 的时间。随后,我们遍历「出现次数数组」,由于堆的大小至多为 k,因此每次堆操作需要 O ( log ⁡ k ) O(\log k) O(logk) 的时间,共需 O ( N log ⁡ k ) O(N\log k) O(Nlogk) 的时间。二者之和为 O ( N log ⁡ k ) O(N\log k) O(Nlogk)
空间复杂度: O ( N ) O(N) O(N)。哈希表的大小为 O ( N ) O(N) O(N),而堆的大小为 O ( k ) O(k) O(k),共计为 O ( N ) O(N) O(N)

参考

https://leetcode.cn/problems/top-k-frequent-elements/solution/qian-k-ge-gao-pin-yuan-su-by-leetcode-solution/

Python heapq库的用法介绍

你可能感兴趣的:(LeetCode,算法)