当前位置: 首页 > news >正文

set/map刷力扣题/(哈希表+排序类型)仿函数和捕获-两种方法解决

对于key的接收:set支持的key必须是小于比较(重载<运算符),因为底层是基于红黑树;
unorder_set支持的key必须是转换成整型的(通过哈希映射)且支持等于比较(重载=运算符),底层是基于哈希表;
迭代器差异:set是双向迭代器,支持++,–,set去重+升序;
unordered_set是单向迭代器,仅仅支持++,unordered_set去重+无序
性能分析:set底层是set底层红黑树的增、删、查、改操作的时间复杂度是 (O(log N))
unordered_set底层哈希表的增、删、查操作平均时间复杂度是(O(1))
O(1)是常数次时间复杂度。
详细的:unorder_mapmap的关系同上,都是从三个方面分析:对于key的接受,map要求Key支持小于比较,而unordered_map要求Key支持转成整形且支持等于比较,要理解unordered_map的这个两点要求
得后续我们结合哈希表底层实现才能真正理解,也就是说这本质是哈希表的要求。
迭代器差异unordered_map不去重+无序;map是去重+升序;性能分析:map底层是map底层红黑树的增、删、查、改操作的时间复杂度是 (O(log N))
unordered_map底层哈希表的增、删、查操作平均时间复杂度是(O(1))

前k个高频元素

前k个高频元素
在这里插入图片描述
解法:哈希+仿函数
定义一个哈希表,用pair<int,int>进行封装,让nums中所有的元素都通过映射放置到哈希表中(统计数字的容器,计数),
再申请一个新的vector容器vec来初始化成哈希表中放置的值,最后可以按照任意顺序返回(出现频率最高前k个元素),这里我们也可以先排序,将vec中的值排好序,不仅要拍好序,按照自然数的大小,还需要按照出现的次数多少,排在最前的只能是自然数小的+次数出现最多的(这里要调用哈希表中的计数)。
要实现次数出现最多,可以实现一个仿函数,返回第二个参数second最大的。sort要调用仿函数排序。这样就实现了“sort自然数排序+次数最多”。
最后设置一个vector容器来封装返回的结果,ret,遍历vec,取前k个元素,这前k个元素要去重。

class Solution {
public:struct kvfunction{bool operator()(const pair<int,int> &nums1,const pair<int,int> &nums2){return nums1.second>nums2.second;}};vector<int> topKFrequent(vector<int>& nums, int k) {unordered_map<int,int>up;for(auto &e:nums){up[e]++;}vector<pair<int,int>>vec(up.begin(),up.end());sort(vec.begin(),vec.end(),kvfunction());vector<int>ret;for(int i=0;i<k;i++){ ret.push_back(vec[i].first);}return ret;}
};

改进:不加仿函数,也即是不额外实现取得数字出现次数的函数,但是需要返回的元素(1.自然数顺序;2.次数最多;3.自行去重),还需要依靠哈希表实现。可以在sort内部参数加一个[ &] ,[& ] 意味捕获所有外部变量。即使在sort的生命周期内部没有哈希映射统计数字出现的个数,[& ]仍然可以从外部调用到up(哈希来统计次数)。
[&] 表示 “以引用方式捕获所有外部变量”,其中就包括哈希表 up。

class Solution {
public:vector<int> topKFrequent(vector<int>& nums, int k) {unordered_map<int,int>up;for(auto &e:nums){up[e]++;}vector<pair<int,int>>vec(up.begin(),up.end());sort(vec.begin(),vec.end(),[&](const pair<int,int> &nums1,const pair<int,int> &nums2){return nums1.second>nums2.second;});vector<int>ret;for(int i=0;i<k;i++){ret.push_back(vec[i].first);}return ret;}
};

根据字符出现频率排序

根据字符出现频率排序
在这里插入图片描述
题目解析:
给定一个字符串 s ,根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。
解法:哈希+仿函数

问题:为什么这里的仿函数中要有构造函数?

仿函数是一个独立的结构体(类),它内部的成员变量(如存储频率的引用 up)默认不会自动关联外部的 up。必须通过构造函数,将外部的 up 作为参数传入仿函数,并赋值给内部的成员变量(这里是引用绑定),才能让仿函数 “拿到” 所需的频率数据。

class Solution {
public:struct kvfunction{// 存储外部哈希表的引用(关键:关联统计好的频率数据)unordered_map<char,int>up;// 构造函数:接收外部的哈希表并绑定引用kvfunction( unordered_map<char,int> &map):up(map){}bool operator()(const char & a,const char & b){return up[a] == up[b] ? a>b:up[a]>up[b];}};string frequencySort(string s) {unordered_map<char,int>up;//创建一个哈希映射,第一个参数是字符串,第二个参数是次数for(auto &e:s){up[e]++;}//遍历,统计出次数//排序,按照字符串的ASCII码值排序+出现次数sort(s.begin(),s.end(),[&](const char& a,const char& b){return up[a] == up[b] ? a>b : up[a]>up[b];});return s;}
};

先按字符出现次数(频率)排序,当频率相同时再按字符的 ASCII 码值排序
“频率从高到低,频率相同则 ASCII 码从大到小”
当两个字符的频率相等时(up[a] == up[b]),则按照字符的 ASCII 码值从大到小排序。例如,‘b’ 的 ASCII 码(98)大于 ‘a’(97),若两者频率相同,则 ‘b’ 排在 ‘a’ 前面。

改进:不加仿函数,用[&]以引用方式捕获所有外部变量。

class Solution {
public:string frequencySort(string s) {unordered_map<char,int>up;//创建一个哈希映射,第一个参数是字符串,第二个参数是次数for(auto &e:s){up[e]++;}//遍历,统计出次数//排序,按照字符串的ASCII码值排序+出现次数sort(s.begin(),s.end(),[&](const char& a,const char& b){return up[a] == up[b] ? a>b : up[a]>up[b];});return s;}
};

其中[&]意为从Up哈希统计次数中取得频次,[&]的存在使得sort可以向上取得char类型的字符在哈希映射中的次数。
[&] 表示 “以引用方式捕获所有外部变量”,其中就包括哈希表 up。

前k个高频单词

前k个高频单词
在这里插入图片描述
解法:详细见博主之前发过的一篇博客:set_map的实现+set/map加持秒杀高频算法题锻炼算法思维最后一题:
这里更新另外一种可以不写仿函数的做法,在sort参数中引进[&],用于捕获外部元素。向上搜索到up哈希,用来 获取字符出现的频次。sort一方面可以实现一堆单词,首先按照频次进行比较,其次按照字典序进行排序。
仿函数引进:来实现这道题:

class Solution {
public:struct kvFunction{bool operator()(const pair<string,int>w1,const pair<string,int>w2){return w1.second>w2.second;//表示次数多的排在前面}};vector<string> topKFrequent(vector<string>& words, int k) {map<string,int>countMap;for(auto& it:words){countMap[it]++;}//统计每一个单词出现的次数vector<pair<string,int>>v(countMap.begin(),countMap.end());//将一个键值对转换为一个vector容器,方便后序排序stable_sort(v.begin(),v.end(),kvFunction());//稳定排序(出现次数相同,保持原map中的字典序)vector<string>ret;for(int i=0;i<k;i++){ret.push_back(v[i].first);}return ret;}
};

改进:引进[&]

class Solution {
public:vector<string> topKFrequent(vector<string>& words, int k) {unordered_map<string,int>up;for(auto &e:words){up[e]++;}vector<pair<string,int>>vec(up.begin(),up.end());sort(vec.begin(),vec.end(),[&](const pair<string,int> &words1,const pair<string,int> & words2){if(words1.second == words2.second)//如果频次相同,字典序小的在前面{return words1.first < words2.first;//字典序小的在前面}else{return words1.second>words2.second;}//否则频次多的在前面});vector<string>ret;for(int i=0;i<k;i++){ret.push_back(vec[i].first);}return ret;}
};
http://www.dtcms.com/a/549141.html

相关文章:

  • 基于单片机与 DeepSeek-OCR 的盲人辅助阅读器设计与实现
  • 淘客网站cms怎么做肥乡专业做网站
  • 【底层机制】Android GC -- 为什么要有GC?GC的核心原理?理解GC的意义
  • 自动驾驶中的传感器技术76——Navigation(13)
  • 鸿蒙Flutter三方库适配指南: 05.使用Windows搭建开发环境
  • 律所网站建设方案书怎么写网站制作排名优化
  • 谷歌网站排名搭建一个平台要多少钱
  • 使用Node.js连接 OPC UA Server
  • h5游戏免费下载:保护堆芯
  • 怎么看网站关键词排名恩施网站制作
  • Jenkins 持续集成与部署
  • 企业查询网站有哪些深圳工业产品设计公司
  • 解析平面卷积/pytorch的nn.Conv2d的计算步骤,in_channels与out_channels如何计算而来
  • 医疗器械经营许可证识别技术通过OCR与AI技术实现资质信息自动提取,显著提升行业效率与合规管理水平
  • Lombok 不生效 —— 从排查到可运行 Demo(含实战解析)
  • 【自然语言处理】预训练02:近似训练
  • 具身智能革命:富唯智能如何用“认知机器人”重塑柔性智造新纪元
  • 孤能子视角:文明演化的适配性考验——从EIS理论看中美技术路径分野
  • itunes礼品卡兑换【完整协议方案】
  • High Rank Adaption系列文章
  • wordpress 网站迁移如何做网站霸屏
  • Rust 中 Raft 协议的云原生深度集成与实践最佳实践
  • html css js网页制作成品——掌心电视剧HTML+CSS网页设计(4页)附源码
  • 基于用户的协同过滤算法实现小说推荐算法
  • 速卖通新客优惠券采购:砍单率高的核心原因
  • 【11408学习记录】考研数学概率论核心突破:一维随机变量函数分布——公式法 分布函数法精讲!​
  • Flutter 网络通信协议:从原理到实战,选对协议让 APP 飞起来
  • 【机器学习入门】9.2:感知机的工作原理 —— 从模型结构到实战分类
  • Flutter---个人信息(3)---实现修改性别
  • 做个网站需要什么制作软件的网站