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

51 阅读3分钟

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

  • 题目输入
  1. 一个整数数组 nums
  2. 一个整数k
  • 题目输出

返回其中出现频率前 k 高的元素,并且返回的数组元素按升序排列

  • 题目解答(C++):

先利用STL容器map(键为元素实际值,值为每个元素的出现次数)存储nums数组元素,该容器会根据键(key)自动排序,默认为从小到大,所以再次利用c++中优先队列priority_queue来储存nums数组中所有元素,优先队列中默认元素从大到小排序,这样既可以找到出现频率前k高的元素,还可以进行升序排列

  • 主要算法容器应用(优先队列)

    • 简介: 在C++标准库中,priority_queue 是一种非常常用的容器适配器,广泛应用于调度系统、图算法中的最短路径问题等场景。priority_queue 提供了一种以堆(heap)为底层结构的优先队列,支持高效的插入和最大(或最小)元素的提取操作priority_queue 是一个存储元素的容器适配器,它能确保队列中的元素按照优先级顺序进行排序。通常来说,默认的priority_queue最大堆,即每次弹出时获取的是当前队列中的最大元素。通过priority_queue<int, std::vector<int>, std::greater<int>>该设置可定义最小堆用户也可以通过自定义比较函数将其转化为其他形式。

    • 底层结构:堆(Heap)

    • 时间复杂度

      • 插入元素的时间复杂度是O(log n)
      • 获取和移除最大或最小元素的时间复杂度是O(log n)
    • 常见操作:

      • 插入元素:push()
      • 获取队首元素:top()
      • 删除队首元素:pop()
      • 判断队列是否为空:empty()
      • 获取队列的大小:size()
  • 本题解答代码

    std::string solution(std::vector<int> nums, int k) {
      map<int, int> mp; // 创建一个 map,用于存储整数及其出现次数
      for (auto s : nums) {
        mp[s]++;// 统计每个整数出现的次数
      }
      //创建一个优先队列,存储 pair<int, int>,其中 first 表示出现次数,second 表示整数
      priority_queue<pair<int,int> >ans;
      for (auto s : mp) {
      // 将整数及其出现次数的 pair 放入优先队列中,按照出现次数降序排列
        ans.push({s.second,s.first});
      }
      string anss;
      int kk=k;
      while(!ans.empty()&&kk>0)
      {
      // 获取优先队列的队首元素,即出现次数最多的整数及其出现次数
        auto[x,y]=ans.top();
        if(kk==k)
        {
      //to_string函数将整数转换为字符串
          anss+=to_string(y);
        }
        else {anss+=',';
        anss+=to_string(y);
        }
        kk--;
        //弹出队尾元素
        ans.pop();
      }
      //返回结果
      return anss;
    }
    
  • 时间复杂度分析
  1. 遍历nums向量统计每个整数出现次数,时间复杂度为O(n) ,其中nnums的长度。
  2. 遍历统计结果的map并将整数及其出现次数的对插入优先队列,时间复杂度为O(m) ,其中m是不同元素的个数。
  3. 循环从优先队列中取出前k个元素,时间复杂度为O(klogn),其中n是优先队列中元素的个数,最坏情况是n等于nums的长度。总体时间复杂度近似为O(n+klogn)。