题目解析 69. 查找热点数据问题 | 豆包MarsCode AI刷题

41 阅读2分钟

人生苦短,我用Python。这个题用heapq秒解。能调库解决的事情就不需要动手。请叫我调包大师。

题目要求找出数组 nums 中出现频率前 k 高的元素,并以升序排序后返回一个逗号分隔的字符串。这需要综合考虑频率统计、高效排序以及符合时间复杂度要求的实现。

问题描述

题目要求找出数组 nums 中出现频率前 k 高的元素,并以升序排序后返回一个逗号分隔的字符串。这需要综合考虑频率统计、高效排序以及符合时间复杂度要求的实现。

解题思路

为了满足时间复杂度优于 O(nlog⁡n)O(n \log n) 的要求,常规的对整个数组排序的方式不可行。我们需要借助 哈希表统计频率堆优化高频选择 来实现。

具体思路如下:

  1. 统计元素频率
    使用哈希表(collections.Counter)统计数组中每个元素的出现频率。这样可以在 O(n)O(n) 的时间内完成频率统计。
  2. 选择频率前 k 高的元素
    利用 Python 的 heapq.nlargest 方法,能在 O(n+klog⁡k) 的时间内提取出频率最高的 k 个元素。这是因为 heapq.nlargest 使用了小顶堆进行优化,不需要对所有元素排序。
  3. 结果排序
    对提取出来的 k 个元素进行升序排序,时间复杂度为 O(klog⁡k)。
  4. 结果格式化
    最后将排序后的结果转化为逗号分隔的字符串。

通过以上步骤,我们可以在满足时间复杂度要求的前提下完成题目要求。

代码实现

from collections import Counter
import heapq

def solution(nums, k):
    freq = Counter(nums)
    most_frequent = heapq.nlargest(k, freq.keys(), key=lambda x: freq[x])
    most_frequent.sort()
    return ','.join(map(str, most_frequent))

通过 Counter(nums) 构建一个字典,键是数组中的唯一元素,值是对应的出现频率。例如:

nums = [1, 1, 1, 2, 2, 3]
freq = {1: 3, 2: 2, 3: 1}

heapq.nlargest 按频率从高到低提取出前 k 个元素。

对于 nums = [1, 1, 1, 2, 2, 3]k = 2,此步骤得到:

most_frequent = [1, 2]

按升序对提取的高频元素排序,确保输出符合要求。

时间复杂度分析

  1. 统计频率
    统计频率的时间复杂度是 O(n),其中 n 是数组 nums 的长度。

  2. 提取前 k 个高频元素
    利用小顶堆实现的 heapq.nlargest,时间复杂度为 O(n+klog⁡k)。

  3. 排序
    对提取的 k 个元素排序,时间复杂度是 O(klog⁡k)。

  4. 总复杂度
    综合上述步骤,总时间复杂度为:

    O(n)+O(n+klog⁡k)+O(klog⁡k)=O(n+klog⁡k)

    由于 k≤n,因此总复杂度优于 O(nlog⁡n)。