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

44 阅读4分钟

69. 查找热点数据问题

在很多数据分析场景中,频率分析是一个常见的需求。给定一个整数数组 nums,以及一个整数 k,要求我们返回数组中频率最高的 k 个元素,并且返回的结果应该是按升序排列的字符串。这个问题不仅涉及到高效的频率统计,还要求我们在保证时间复杂度优于 O(n log n) 的前提下,快速找到并返回结果。本文将详细解析解决该问题的思路、步骤及代码实现,并讨论其中的优化策略。

问题分析

输入与输出

输入:
  • nums:一个正整数数组,长度为 n,数组中可能有重复元素。
  • k:一个整数,表示要求返回的前 k 个高频元素。
输出:
  • 返回一个字符串,其中包含出现频率前 k 高的元素,数字之间用逗号分隔,并且按升序排列。

限制:

  • 数组长度 n 最大为 10^5,数组中的元素值范围为 1 到 10^4。
  • k 的值范围为 [1, 数组中不相同的元素的个数]。

思路分析

  1. 统计元素频率: 我们需要首先统计每个元素的出现频率。可以利用哈希表(如 defaultdict)来完成这个任务,其时间复杂度为 O(n),其中 n 是数组的大小。

  2. 高频排序: 一旦知道了每个元素的频率,我们就可以根据频率进行排序。直接使用 Python 的 sorted 函数会有 O(n log n) 的时间复杂度,但是为了优化,我们可以使用桶排序(Bucket Sort)的思想,将频率作为桶的索引,元素的值作为桶内的元素。

  3. 从桶中选出前 k 个元素: 我们从频率最大的桶开始,依次选取元素,直到选出前 k 个元素。因为桶排序的特点是根据频率进行分组,所以我们可以确保首先选出的元素就是高频元素。

  4. 最终结果排序: 选出前 k 个元素后,我们需要将这些元素按升序排列。

  5. 返回结果: 将前 k 个元素按要求拼接成字符串返回。

算法步骤

1. 统计元素频率

首先,我们使用一个哈希表(defaultdict)来统计数组中每个元素出现的次数。

2. 桶排序

利用桶排序的思想,我们为每个频率值创建一个桶。桶的索引表示频率,桶内的元素是具有该频率的所有数值。

3. 选择前 k 个元素

从频率最大的桶开始,逐一选出元素,直到选满 k 个。

4. 升序排列并返回

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

代码实现

from collections import defaultdict

def solution(nums, k):
    # 步骤 1: 统计频率
    freq_map = defaultdict(int)
    for num in nums:
        freq_map[num] += 1
        
    # 步骤 2: 使用桶排序的思想
    # 创建桶,桶的索引是频率,桶的值是对应频率的元素列表
    max_freq = max(freq_map.values())
    buckets = [[] for _ in range(max_freq + 1)]
    
    # 将元素放到对应频率的桶中
    for num, freq in freq_map.items():
        buckets[freq].append(num)
    
    # 步骤 3: 从高频到低频选出前 k 个元素
    result = []
    for i in range(max_freq, 0, -1):
        if buckets[i]:
            result.extend(buckets[i])
        if len(result) >= k:
            break
            
    # 步骤 4: 选出前 k 个元素后,按升序排列
    result = result[:k]
    result.sort()
    
    # 步骤 5: 将结果转换为字符串并返回
    return ",".join(map(str, result))

时间复杂度分析

  1. 统计频率:这一步需要遍历数组一次,时间复杂度为 O(n),其中 n 是数组的大小。
  2. 桶排序:我们创建了 max_freq + 1 个桶,并将每个元素放入相应的桶中。由于桶的数量与数组中的最大频率成正比,因此该步骤的时间复杂度为 O(n)。
  3. 选择前 k 个元素:我们从高频桶中选择元素,最多需要遍历所有桶,因此该步骤的时间复杂度为 O(n)。
  4. 排序:我们对前 k 个元素进行排序,时间复杂度为 O(k log k),其中 k 是结果中的元素个数。