C++ 用哈希表解决《T69.查找热点数据问题》| 豆包MarsCode AI刷题

5 阅读3分钟

题目内容与要求

问题描述

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

输入

  • nums: 一个正整数数组
  • k: 一个整数

返回

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

思路解析

为了高效地解决这个问题,我们需要以下几个步骤:

  1. 统计频率:使用哈希表(unordered_map)来统计每个元素的出现频率。
  2. 构建频率对:将频率信息转换为一个包含频率对的向量(vector<pair<int, int>>),其中每个元素是一个对,包含元素值和对应的频率。
  3. 排序:按频率降序排序这些频率对。
  4. 提取前 k 个元素:从排序后的频率对中提取前 k 个元素的值。
  5. 排序并转换为字符串:对提取出的元素进行排序,并将它们转换为字符串形式,元素之间用逗号分隔。

代码解释

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <unordered_map>
#include <set>
using namespace std;

string solution(vector<int> nums, int k) {
    // 使用unordered_map统计每个元素的出现次数
    unordered_map<int, int> frequency;
    for (int num : nums) {
        ++frequency[num];
    }
    // 将频率信息转换为pair容器
    vector<pair<int, int>> freqs(frequency.begin(), frequency.end());
    // 按频率降序排序
    sort(freqs.begin(), freqs.end(), [](const pair<int, int>& a, const pair<int, int>& b) {
        return a.second > b.second;
    });
    // 提取前k个不同元素
    vector<int> topK;
    for (int i = 0; i < min(k, static_cast<int>(freqs.size())); ++i) {
        topK.push_back(freqs[i].first);
    }
    // 对topK进行排序
    sort(topK.begin(), topK.end());
    // 转换成字符串形式
    string result;
    for (size_t i = 0; i < topK.size(); ++i) {
        if (i != 0) result += ",";
        result += to_string(topK[i]);
    }
    return result;
}

时间复杂度分析

  1. 统计频率

    • 使用 unordered_map 统计每个元素的出现次数,时间复杂度为 O(n),其中 n 是数组的大小。
  2. 构建频率对

    • unordered_map 中的数据复制到 vector<pair<int, int>> 中,时间复杂度为 O(n)。
  3. 排序

    • 使用 std::sort 对频率对进行排序,时间复杂度为 O(n log n)。
  4. 提取前 k 个元素

    • 遍历排序后的频率对,提取前 k 个元素,时间复杂度为 O(k)。
  5. 对结果进行排序

    • 对提取出的前 k 个元素进行排序,时间复杂度为 O(k log k)。
  6. 构建结果字符串

    • 构建结果字符串,时间复杂度为 O(k)。

综合以上步骤,优化后的整体时间复杂度主要由统计频率和排序决定,因此总的时间复杂度为 O(n + n log n) = O(n log n)。

核心知识

  1. 哈希表(unordered_map:用于高效地统计元素的出现频率。
  2. 排序算法(std::sort:用于对频率对进行排序。
  3. 容器(vectorpair:用于存储和处理数据。
  4. 字符串处理:用于将结果转换为字符串形式。

总结

通过使用 unordered_map 统计频率、vector<pair<int, int>> 存储频率对以及 std::sort 进行排序,我们能够高效地找出出现频率最高的前 k 个元素,并按升序排列。这种方法的时间复杂度为 O(n log n),优于原始的 O(n^2) 方法,特别是在处理大规模数据时,性能提升显著。通过这种方式,代码不仅更加简洁易读,而且执行效率也得到了显著提升。