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

108 阅读4分钟

题目解析:查找热点数据问题

题目描述

给你一个整数数组 nums 和一个整数 k,请你用一个字符串返回其中出现频率前 k 高的元素。请按升序排列。

思路

  1. 统计每个元素的频率:使用哈希表(字典)来统计每个元素的出现次数。使用 collections.Counter 来统计每个元素的出现次数。
  2. 构建频率-元素映射:使用一个列表来存储每个频率对应的元素。
  3. 找到前 k 高的频率:使用最小堆(优先队列)来找到前 k 高的频率。
  4. 按升序排列并返回结果:将前 k 高的元素按升序排列,并返回一个字符串。

图解

假设 nums = [4, 4, 4, 2, 2, 2, 3, 3, 1]k = 2

  1. 统计每个元素的频率

    • 4 出现 3 次
    • 2 出现 3 次
    • 3 出现 2 次
    • 1 出现 1 次
  2. 构建频率-元素映射

    • 使用最小堆来维护前 k 高的频率。
    • 最小堆:[(3, 4), (3, 2)]
  3. 按升序排列并返回结果

    • 堆中的元素按升序排列:2, 4
    • 返回字符串:"2,4"

代码详解

python

from collections import Counter
import heapq

def solution(nums, k):
    # 统计每个元素的频率
    count = Counter(nums)
    
    # 使用最小堆找到前 k 高的频率
    min_heap = []
    for num, freq in count.items():
        heapq.heappush(min_heap, (freq, num))
        if len(min_heap) > k:
            heapq.heappop(min_heap)
    
    # 提取前 k 高的元素
    top_k_elements = [num for freq, num in min_heap]
    
    # 按升序排列
    top_k_elements.sort()
    
    # 返回结果字符串
    return ','.join(map(str, top_k_elements))

if __name__ == "__main__":
    # 你可以在这里添加更多的测试用例
    print(solution([1, 1, 1, 2, 2, 3], 2) == "1,2")  # 样例1
    print(solution([1], 1) == "1")  # 样例2
    print(solution([4, 4, 4, 2, 2, 2, 3, 3, 1], 2) == "2,4")  # 样例3

代码解释

  1. 统计每个元素的频率

    count = Counter(nums)
    

    使用 collections.Counter 来统计每个元素的出现次数。

  2. 使用最小堆找到前 k 高的频率

    min_heap = []
    for num, freq in count.items():
        heapq.heappush(min_heap, (freq, num))
        if len(min_heap) > k:
            heapq.heappop(min_heap)
    

    使用最小堆来维护前 k 高的频率。每次插入一个新的频率-元素对时,如果堆的大小超过 k,则弹出堆顶元素(最小的频率)。

  3. 提取前 k 高的元素

    top_k_elements = [num for freq, num in min_heap]
    

    从最小堆中提取前 k 高的元素。

  4. 按升序排列并返回结果

    top_k_elements.sort()
    return ','.join(map(str, top_k_elements))
    

    将前k高的元素按升序排列,并返回一个字符串。

通过这种方法,我们可以在O(nlog⁡k)的时间复杂度内解决这个问题,有效地找到并返回前k高的元素。

知识总结

  1. 哈希表(字典) :用于快速统计每个元素的出现次数。
  2. 最小堆(优先队列) :用于高效地找到前 k 高的频率。最小堆的插入和删除操作的时间复杂度为 O(log⁡k),因此总的时间复杂度为 O(nlog⁡k)。
  3. 列表推导式:用于简洁地从最小堆中提取元素。
  4. 字符串拼接:使用 join 方法将列表中的元素拼接成一个字符串。

学习建议

  1. 理解数据结构:熟悉哈希表和堆的基本操作及其应用场景。
  2. 掌握常用库:了解 collections.Counter 和 heapq 的用法,这些库提供了高效的统计和堆操作。
  3. 优化算法:在解决类似问题时,考虑如何优化时间复杂度,例如使用堆来替代排序操作。
  4. 多做练习:通过刷题来加深对数据结构和算法的理解,提高编程能力。

问题总结和解决方法

问题1:最小堆的使用不熟练

原因:对最小堆的插入和删除操作不够熟悉。

解决方法:多练习最小堆的操作,理解其内部机制。

问题2:字符串拼接的效率问题

原因:使用 + 操作符拼接字符串会导致多次内存分配,影响性能。

解决方法:使用 join 方法将列表中的元素拼接成一个字符串,效率更高。

问题3:边界条件处理不当

原因:对边界条件(如 k 的取值范围)处理不当。

解决方法:在编写代码时,先考虑边界条件,确保代码正确。

通过这道题目的练习,我不仅巩固了对哈希表和堆的理解,还学会了如何优化算法以提高时间复杂度。希望我的总结和建议能对其他同学有所帮助。