• 前K个高频单词-c++实现


    692. 前K个高频单词 - 力扣(LeetCode)

    给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。

    返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。

    1. 示例 1
    2. 输入: words = ["i", "love", "leetcode", "i", "love", "coding"], k = 2
    3. 输出: ["i", "love"]
    4. 解析: "i""love" 为出现次数最多的两个单词,均为2次。
    5. 注意,按字母顺序 "i""love" 之前。

     我们可以先把 words 当中的单词按照 pair的方式放到 一个 map 当中去,然后使用 sort()函数对 map 当中的 int (词频)进行排序,再把 排好序的 string ,放到一个 string vector 当中返回。

    但是 sort()函数支持的是 随机迭代器,而 map 是双向迭代器,所以 map 不能直接用于 sort()函数,所以,我们想到把 map 当中的数据(key-value)放到一个 vector>当中去,因为 vector 的迭代器是随机迭代器,所以能使用 sort()函数。

    但是,如果我们想要 使用 pair对象当中的 int (词频)来排序的话,在 sort()当中是支持仿函数的设定的,在 sort()的第三个参数,就是仿函数,所以,我们需要自己实现一个 int 比较的仿函数:
     

    1. class Greater
    2. {
    3. bool operator()(const int& x, const int& y)
    4. {
    5. return x > y;
    6. }
    7. };

    然后在调用 sort()函数的时候调用这个 Greater的匿名对象就行了:

    1. // 因为map 的迭代器是双向迭代器,不能用sort(),sort()需要随机迭代器
    2. vectorint>> sortv(StringMap.begin(), StringMap.end());
    3. sort(sortv.begin(), sortv.end(), greater());

    注意,这里给仿函数的形式是给 greater(),匿名对象的形式,因为 sort()函数是以参数列表的形式接收 这个 仿函数(其实就是一个类),所以要接受一个对象。

    而在模版参数当中接收的仿函数,接收的是类型,所以是以 greater 这样的形式给的,如下所示:
     

     当上述工作都完成之后,我们发现,我们输出的结果有误:
     

     由上述结果可知,并不是完全无序的,而是 一组一组 的无序。通过观察发现,是sort()函数的问题,sort()函数的底层是使用快排来实现的,快排是不稳定的排序,所谓不稳定就是,同一个值,应该按照原本在数组当中存储的顺序来进行排序。这才是稳定的,但是 快排是不稳定的。

    所以才出现了上述的输出错误。

    其实在库当中,sort()函数有一个 优化函数 :stable_sort(),这个就是 稳定的 快排。

     完整代码:

    1. class Solution {
    2. public:
    3. // 用于比较 int(词频)的仿函数
    4. // 可以使用 class,但是 class 当中成员不加 权限修饰符默认是 private
    5. // struct 默认是 public 的
    6. struct Greater
    7. {
    8. bool operator()(const pairint>& x, const pairint>& y)
    9. {
    10. return x.second > y.second;
    11. }
    12. };
    13. // 主函数
    14. vector topKFrequent(vector& words, int k) {
    15. mapint> StringMap;
    16. for(auto e : words)
    17. {
    18. StringMap[e]++;
    19. }
    20. // 因为map 的迭代器是双向迭代器,不能用sort(),sort()需要随机迭代器
    21. vectorint>> sortv(StringMap.begin(), StringMap.end());
    22. stable_sort(sortv.begin(), sortv.end(), Greater());
    23. vector retvector;
    24. for(int i = 0;i < k;i++)
    25. {
    26. retvector.push_back(sortv[i].first);
    27. }
    28. return retvector;
    29. }
    30. };

    当然,使用 sort()函数也可以解决,sort()函数不稳定,我们在 仿函数比较规则当中控制就可以了(控制,当词频相同时候,string排序当中小的在前):

    1. class Solution {
    2. public:
    3. // 用于比较 int(词频)的仿函数
    4. // 可以使用 class,但是 class 当中成员不加 权限修饰符默认是 private
    5. // struct 默认是 public 的
    6. struct Greater
    7. {
    8. bool operator()(const pairint>& x, const pairint>& y)
    9. {
    10. // 控制,当词频相同时候,string排序当中小的在前
    11. return x.second > y.second || (x.second == y.second && x.first < y.first);
    12. }
    13. };
    14. // 主函数
    15. vector topKFrequent(vector& words, int k) {
    16. mapint> StringMap;
    17. for(auto e : words)
    18. {
    19. StringMap[e]++;
    20. }
    21. // 因为map 的迭代器是双向迭代器,不能用sort(),sort()需要随机迭代器
    22. vectorint>> sortv(StringMap.begin(), StringMap.end());
    23. sort(sortv.begin(), sortv.end(), Greater());
    24. vector retvector;
    25. for(int i = 0;i < k;i++)
    26. {
    27. retvector.push_back(sortv[i].first);
    28. }
    29. return retvector;
    30. }
    31. };

    其实不使用 sort()之类的排序函数也是可以实现的,map 本身在输出的时候就有排序的效果,我们可以先用map 按string 来排序(string作为key),再用 int(词频)来排序就可以实现了(int 作为 key)。

    但是注意,我们要的结果是降序的前 k 个,但是 map 默认是 升序的,如果 默认升序的后 k 个话,string 排序是反的。

    其实,map 还有一个模版参数,可以控制升序和降序:

     他默认是 less()仿函数,我们传入一个库当中的 greater()仿函数就可以了:
    完整代码实现:
     

    1. class Solution {
    2. public:
    3. // 主函数
    4. vector topKFrequent(vector& words, int k) {
    5. // 排序string
    6. mapint> StringMap;
    7. for(auto e : words)
    8. {
    9. StringMap[e]++;
    10. }
    11. // 排序 int(词频)
    12. multimap<int, string , greater<int>> intMap;
    13. for(auto& e : StringMap)
    14. {
    15. intMap.insert(make_pair(e.second, e.first));
    16. }
    17. vector retvector;
    18. auto it = intMap.begin();
    19. while(k--)
    20. {
    21. retvector.push_back(it->second);
    22. it++;
    23. }
    24. return retvector;
    25. }
    26. };

     还可以使用 set 来实现,也是写仿函数按照 出现 频率去比,当出现频率相同,手动判断,然后进行处理(再去按照字典排)。

    代码实现:
     

    1. class Solution {
    2. public:
    3. class Compare
    4. {
    5. public:
    6. // 在set中进行排序时的比较规则
    7. bool operator()(const pairint>& left, const
    8. pairint>& right)
    9. {
    10. return left.second > right.second;
    11. }
    12. };
    13. vector topKFrequent(vector& words, int k)
    14. {
    15. // 用<单词,单词出现次数>构建键值对,然后将vector中的单词放进去,统计每
    16. //个单词出现的次数
    17. mapint> m;
    18. for (size_t i = 0; i < words.size(); ++i)
    19. ++(m[words[i]]);
    20. // 将单词按照其出现次数进行排序,出现相同次数的单词集中在一块
    21. multisetint>, Compare> ms(m.begin(), m.end());
    22. // 将相同次数的单词放在set中,然后再放到vector中
    23. set s;
    24. size_t count = 0; // 统计相同次数单词的个数
    25. size_t leftCount = k;
    26. vector ret;
    27. for (auto& e : ms)
    28. {
    29. if (!s.empty())
    30. {
    31. // 相同次数的单词已经全部放到set中
    32. if (count != e.second)
    33. {
    34. if (s.size() < leftCount)
    35. {
    36. ret.insert(ret.end(), s.begin(), s.end());
    37. leftCount -= s.size();
    38. s.clear();
    39. }
    40. else
    41. {
    42. break;
    43. }
    44. }
    45. }
    46. count = e.second;
    47. s.insert(e.first);
    48. }
    49. }
    50. }

  • 相关阅读:
    安科瑞微电网智慧能源平台【能源规划、协调控制、经济运行】
    python简单制作whl安装包
    域对象共享数据
    目标检测YOLO实战应用案例100讲-面向小目标检测的多尺度特征融合(续)
    NSDT孪生场景编辑器系统介绍
    【数据结构】list.h 详细使用教程 -- 附带例子代码
    【Java】泛型讲解
    带背景音乐的css3桃子桃花背景
    灰鸽子木马特征值免杀
    SpringBoot使用Nacos作为配置中心服务
  • 原文地址:https://blog.csdn.net/chihiro1122/article/details/132896809