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

34 阅读3分钟

问题描述

给你一个整数数组 nums 和一个整数 k,请你用一个字符串返回其中出现频率前 k 高的元素。请按升序排列。 你所设计算法的时间复杂度必须优于 O(n log n),其中 n 是数组大小。

输入

nums: 一个正整数数组

k: 一个整数

返回

返回一个包含 k 个元素的字符串,数字元素之间用逗号分隔。数字元素按升序排列,表示出现频率最高的 k 个元素。

参数限制

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

测试样例

样例1:

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

输出:"1,2"

解释:元素 1 出现了 3 次,元素 2 出现了 2 次,元素 3 出现了 1 次。因此前两个高频元素是 1 和 2。

样例2:

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

样例3:

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

解题思路

统计频率:首先,我们需要统计数组中每个元素的出现频率。可以使用 collections.Counter 来快速实现这一点。 排序:然后,我们需要根据频率对元素进行排序。由于题目要求时间复杂度优于 O(n log n),我们可以使用堆(heap)来实现这一步。 选择前 k 个:最后,我们从堆中取出前 k 个元素。

代码实现(以Python形式)

from collections import Counter
import heapq

def solution(nums, k):
    # 统计每个元素的频率
    frequency = Counter(nums)

    # 使用最小堆来找到频率前 k 高的元素
    min_heap = []
    for num, freq in frequency.items():
        # 将频率和元素的负值(因为我们需要最大堆)放入堆中
        heapq.heappush(min_heap, (freq, -num))
        # 如果堆的大小超过 k,弹出最小的元素
        if len(min_heap) > k:
            heapq.heappop(min_heap)

    # 从堆中取出前 k 个元素,并按升序排列
    result = [-num for _, num in min_heap]
    result.sort()

    return result

if __name__ == "__main__":
    #  You can add more test cases here
    print(solution([1,1,1,2,2,3], 2) == [1,2])
    print(solution([1], 1) == [1])

关键步骤解释

统计频率: frequency = Counter(nums) 这行代码使用 Counter 来统计每个元素的出现频率。 使用最小堆:

min_heap = []

for num, freq in frequency.items():
    heapq.heappush(min_heap, (freq, -num))
    if len(min_heap) > k:
        heapq.heappop(min_heap)

这里我们使用最小堆来维护频率前 k 高的元素。由于 heapq 默认是最小堆,我们需要将元素的频率和元素的负值放入堆中,以便在弹出时得到频率最高的元素。

取出前 k 个元素并排序 result = [-num for _, num in min_heap] result.sort()

最后,我们从堆中取出前 k 个元素,并按升序排列。

可能面对的问题 : 如何使用哈希表来统计元素的频率?

使用哈希表(在 Python 中通常使用 collections.Counter)来统计元素的频率是一个非常高效的方法。Counter 是 collections 模块中的一个类,它可以帮助我们快速统计列表中每个元素的出现次数。

代码示例

from collections import Counter

def solution(nums, k):
    # 使用 Counter 统计每个元素的频率
    frequency = Counter(nums)

    # 打印频率统计结果
    print(frequency)

    # 继续你的代码逻辑...

if __name__ == "__main__":
    nums = [1, 1, 1, 2, 2, 3]
    k = 2
    solution(nums, k)

解释

导入 Counter: from collections import Counter

首先,我们需要从 collections 模块中导入 Counter 类。

统计频率: frequency = Counter(nums)

这行代码会创建一个 Counter 对象 frequency,它包含了 nums 列表中每个元素的出现次数。例如,对于 nums = [1, 1, 1, 2, 2, 3],frequency 将会是 Counter({1: 3, 2: 2, 3: 1})。

打印频率统计结果: print(frequency)

示例输出:

对于 nums = [1, 1, 1, 2, 2, 3],输出将会是:

Counter({1: 3, 2: 2, 3: 1})

总结

在统计完频率之后,你可以继续使用这些频率信息来实现你的算法逻辑,例如使用堆来找到频率前 k 高的元素。