首页 > 编程语言 >C++算法练习-day27——347.前k个高频元素

C++算法练习-day27——347.前k个高频元素

时间:2024-10-30 14:49:37浏览次数:9  
标签:频率 堆顶 day27 元素 C++ 347 哈希 数组 自定义

题目来源:. - 力扣(LeetCode)

题目思路分析

题目:找出数组中出现频率最高的前K个元素。

这个问题要求我们从给定的数组nums中找出频率最高的前k个元素。这通常意味着我们需要统计每个元素的出现次数,然后根据这些次数进行排序,并提取前k个元素。以下是解决这个问题的思路:

  1. 统计频率:首先,我们需要统计每个元素在数组中出现的次数。这可以通过使用一个哈希表(如unordered_map)来实现,其中键是数组中的元素,值是该元素出现的次数。

  2. 构建最小堆:接下来,我们需要一个数据结构来高效地获取频率最高的前k个元素。由于堆(特别是最小堆)可以在对数时间内插入和删除元素,并且总是保持堆顶元素为最小(或最大,取决于堆的类型),所以它是这个问题的理想选择。在这个问题中,我们将使用最小堆,但堆中的元素将按频率的负值排序(或者直接使用最大堆),以便堆顶始终是频率最高的元素。然而,为了简化,这里我们使用priority_queue配合自定义比较函数来实现最大堆的效果。

  3. 维护堆的大小:在遍历哈希表时,我们将元素及其频率添加到堆中。如果堆的大小超过了k,我们就从堆中移除堆顶元素(当前频率最低的元素),以确保堆中始终只有频率最高的k个元素。

  4. 提取结果:最后,我们从堆中提取元素,并将它们添加到结果数组中。由于堆是按照频率排序的,所以这些元素将按频率从高到低的顺序排列。

代码:

#include <vector>  
#include <unordered_map>  
#include <queue>  
#include <utility>  
  
using namespace std;  
  
class Solution {  
public:  
    // 自定义比较函数,用于构建最大堆  
    static bool cmp(pair<int,int>& m,pair<int,int>& n){  
        return m.second<n.second; // 注意这里使用小于号,因为我们传递给priority_queue的是cmp的指针,priority_queue默认是大顶堆,所以这里实现小顶堆的效果,但逻辑上我们视为最大堆(频率高的在上面)  
    }  
      
    vector<int> topKFrequent(vector<int>& nums, int k) {  
        unordered_map<int,int> pos; // 用于存储每个数字及其出现次数的哈希表  
        for(int& e:nums){  
            ++pos[e]; // 统计每个数字的出现次数  
        }  
          
        // 使用自定义比较函数cmp构建priority_queue(逻辑上视为最大堆)  
        priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(&cmp)> q(cmp);  
          
        // 遍历哈希表,将元素及其频率添加到堆中  
        for(auto& [num,count] : pos){  
            if(q.size()==k){  
                // 如果堆已满,检查当前元素频率是否高于堆顶元素频率  
                if(q.top().second<count){  
                    q.pop(); // 移除堆顶元素  
                    q.emplace(num,count); // 添加当前元素  
                }  
            }  
            else{  
                q.emplace(num,count); // 堆未满,直接添加当前元素  
            }  
        }  
          
        vector<int> ans; // 存储结果的数组  
        while(!q.empty()){  
            ans.push_back(q.top().first); // 提取堆顶元素(频率最高的元素)  
            q.pop(); // 移除堆顶元素  
        }  
          
        // 由于是从堆中逐个提取的,所以结果需要反转以恢复原始频率顺序(从高到低)  
        reverse(ans.begin(), ans.end()); // 但题目并未明确要求顺序,此步可省略  
          
        return ans; // 返回结果数组  
    }  
};

知识点摘要

  1. 哈希表(unordered_map:用于快速查找和统计元素的出现次数。
  2. 堆(priority_queue:用于高效地获取最大或最小元素,支持对数时间复杂度的插入和删除操作。
  3. 自定义比较函数:用于在堆中根据元素的频率进行排序。
  4. 范围for循环(for(auto& x : y):用于遍历容器中的元素。

本文介绍了如何使用哈希表和堆来解决找出数组中出现频率最高的前K个元素的问题。我们首先使用哈希表统计每个元素的出现次数,然后使用堆来维护频率最高的前K个元素。这种方法结合了哈希表的快速查找能力和堆的高效排序能力,是解决此类问题的有效方法。通过理解哈希表和堆的工作原理,以及如何自定义比较函数来构建堆,我们可以更好地解决类似的问题。

标签:频率,堆顶,day27,元素,C++,347,哈希,数组,自定义
From: https://blog.csdn.net/L613Z/article/details/142992488

相关文章

  • 探索C++的类与继承之美:从基础到高级
    C++是一种强大的面向对象编程语言,其特性允许开发者利用类和继承来构建复杂的数据结构和功能。在本篇博客中,我们将通过一些示例代码,详细解析C++中的类、继承、虚继承、访问控制以及多重继承的概念。类的定义与基本特性类是C++的基本构建块,允许我们定义一个新的数据类型,该类型......
  • C++接口集成、身份实名认证-游戏防沉迷,保障未成年人健康
    随着互联网的快速发展,网络游戏在年轻人中越来越受欢迎。然而,未成年玩家长时间沉迷游戏的问题却引发了社会的广泛关注。为了应对这一现象,各大网络游戏平台纷纷引入翔云身份证实名认证接口,以有效辨别用户身份,建立完善的防沉迷系统,从而更好地保护未成年玩家的身心健康。......
  • 【C++】string 类深度解析:探秘字符串操作的核心
     快来参与讨论......
  • 我接触csdn中的c++的时间
    大家好,我是AC使者,不知不觉我也来到CSDN半年了!在这半年我也看到了自身的不足,我也还有了很多粉丝,所以我今天来总结一下这半年的东西。第一篇--------结构体数组关于结构体数组的理解-CSDN博客第二篇--------字符串C05.L06.字符串合并_c++字符串合并-CSDN博客第三篇--------......
  • C++练习:股票买卖的最佳时机(1~4)
    121.买卖股票的最佳时机简介这是一道简单题,思路是找卖出那一天前的最低价格,然后记录卖出后的最大利润。按照动态规划的思路解题,我们需要找到原问题和子问题的转移关系。分析:n天内的最大利润,一定是1~n内某一天卖出股票的最大利润。我们知道要使我们手中的股票得到最大利润,就......
  • list(c++)
    list介绍list是STL容器中的容器,且元素在容器中的位置是分散的并与大小无关。list的底层是双向链表,其优势是在任意位置插入和删除元素的时间复杂度为O(1),但无法通过“下标[]”直接访问元素,需要通过从头(尾)遍历元素找到元素,多用于需要大量数据的插入和删除,且对数据的随机访问比......
  • 基于 C++ 的 UG/NX 二次开发环境配置
    基于C++的UG/NX二次开发环境配置参考教程:UG/NX二次开发环境配置方法(nx1980+vs2019)-CSDN博客NX二次开发VS环境搭建-怡宁塑胶模具设计-博客园(cnblogs.com)NX/UG二次开发环境配置方法—史上最详细版(以NX11.0和VisualStudio2017为例)_nx二次开发-CSDN博客在Windows......
  • C++:日期类的实现
      目录一.日期类1.类的构造函数和拷贝构造2.日期的比较3.日期加减一个天数1.日期加天数2.日期减天数4.日期的++与--1.日期的++2.日期的--5.日期减日期6.日期的输入和输出二.整体代码1.Date.h2.Date.cpp      在前面几节的内容中,我们学习了类的基本......
  • 【C/C++】5.并发控制
    并发控制(ConcurrencyControl)是指在多线程或多进程环境中,确保多个操作在共享资源上的访问不会发生冲突或产生不一致的情况。并发控制的核心目标是在允许并发操作的同时,保证系统的正确性、数据的一致性和完整性。在并发环境下,不同的线程或进程可能会同时访问共享资源(例如变量、文......
  • 每日OJ题_牛客_AB20走迷宫_BFS_C++_Java
    目录牛客_AB20走迷宫_BFS题目解析C++代码Java代码牛客_AB20走迷宫_BFS走迷宫_牛客题霸_牛客网(nowcoder.com)描述:        给定一个n×m的网格,在网格中每次在不超过边界的情况下可以选择向上、向下、向左、向右移动一格。网格中的一些格子上放置有障碍物,放有......