NO.69-AI刷题题解 | 豆包MarsCode AI刷题

163 阅读3分钟

NO.69 查找热点数据问题

问题描述

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按任意顺序返回答案。

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

你所设计算法的时间复杂度必须优于 O(n log n) ,其中 n 是数组大小。

示例 1

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

输出: [1,2]

示例 2

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

输出: [1]

测试案例分析

nums = {4,4,4,2,2,2,3,3,1}, k = 3 为例:

  1. 出现频率依次为{数字,频数}: {4, 3}, {2, 3}, {3, 2}, {1, 1}
  2. 取频率前 k 高的元素,即4, 2, 3
  3. 有序排列:[2,3,4]

最终返回值为 "2,3,4"

题目解析

  1. 首先,我们需要构建一个 vector<pair<int,int>>arr 用于存储初始 nums 中的数字和对应的频数
  2. 然后,我们需要根据频数对 arr 中的 pair 进行降序排序,以便找到其中出现频率前 k 高的元素
  3. 接着,我们需要取出出现频率前 k 高的元素存入 vector<int>result
  4. 另外,我们需要对 result 中的元素按照数字大小升序排序
  5. 最后,我们对 result 中的元素按照题目所需的格式返回 string

定义变量如下:

  • 记录 nums 中的数字和对应的频数:vector<pair<int,int>>arr
  • 记录某数字出现的频数:count
  • 记录目前所在索引位置:pos
  • 记录前 k 个高频元素的集合:vector<int> result

代码实现

#include <vector>
#include <string>
#include <algorithm>

using namespace std;

std::string solution(std::vector<int> nums, int k) {
    sort(nums.begin(),nums.end());
    vector<pair<int,int>>arr(nums.size());
    int count=0;
    int pos=0;
    for(int i=0;i<nums.size();i++){
        if(i==0 || nums[i]==nums[i-1]){
            count++;
        } 
        else {
            arr[pos] = make_pair(nums[i-1], count);
            count=1; //此时与上一索引对应数组的值不同,个数重新初始化,且为1 
            pos++;
        }
    }arr[pos] = make_pair(nums.back(), count); //处理最后一个元素 
    
	sort(arr.begin(), arr.end(), [](pair<int, int>& a, pair<int, int>& b) {
        return a.second > b.second; // 按频率降序
    });
    
    vector<int> result;
    for (int i = 0; i < k; i++) {    //取出前k个元素
        result.push_back(arr[i].first);
    }
    
    sort(result.begin(),result.end()); //对返回结果按照升序排序 

    string rst;
    for(int j=0;j<k;j++){ //匹配题目所需返回格式 
        rst.push_back('0'+result[j]);
        if(j!=k-1) rst.push_back(',');
    }
    return rst;
}

注意:

  • 初始化时,使用 sort 对 nums 进行排序,能避免在 arr 中还需对乱序的数字输入进行处理,有效降低了时间复杂度
  • 在遍历 nums 并更新 arr 后,count 需重置,由于此时处在与前元素不同的第一个数的位置,所以 count = 1
  • 在遍历 nums 并记录 count 时,对于最后一个元素需要单独处理,否则会漏掉最后一个元素的记录
  • 对 arr 根据频数进行降序排列使用 sort 方法: sort(arr.begin(), arr.end(), [](pair<int, int>& a, pair<int, int>& b) { return a.second > b.second; });
  • 题目测试案例要求对最终输出按照元素数字大小升序排序,故需要对 result 进行 sort(result.begin(),result.end()) 的额外处理
  • 本解法的时间复杂度为 O(nlogn)