• 【算法】priority_queue在力扣题中的应用 | 力扣692 | 力扣347 | 力扣295 【超详细的注释和算法解释】


     


    说在前面的话

    博主也好长一段时间没有更新力扣的刷题系列了,今天给大家带来一些优先队列的经典题目,今天博主还是用C++给大家讲解,希望大家可以从中学到一些东西。

    前言

    那么这里博主先安利一下一些干货满满的专栏啦!

    手撕数据结构https://blog.csdn.net/yu_cblog/category_11490888.html?spm=1001.2014.3001.5482这里包含了博主很多的数据结构学习上的总结,每一篇都是超级用心编写的,有兴趣的伙伴们都支持一下吧!
    算法专栏https://blog.csdn.net/yu_cblog/category_11464817.html这里是STL源码剖析专栏,这个专栏将会持续更新STL各种容器的模拟实现。

    STL源码剖析https://blog.csdn.net/yu_cblog/category_11983210.html?spm=1001.2014.3001.5482


    priority_queue 优先队列

    优先队列的底层实现就是数据结构的堆。其中,小顶堆可以不断更新数组里的最小值,大顶堆可以不断更新数组里的最大值,push和pop自带排序功能,经常用来解决TopK问题。

    如果大家有需要数据结构堆的实现可以通过博主的传送门食用噢~

    【堆】数据结构-堆的实现【超详细的数据结构教学】icon-default.png?t=M85Bhttps://blog.csdn.net/Yu_Cblog/article/details/124944614

    692.前K个高频单词

     看到频率,我们很自然可以想到哈希表,我们可以用哈希表记录每个单词出现的次数。看到前K个,可以断定这是一个topK问题,我们需要用到优先队列。但是,哈希表是单向的映射,因此我们还需要用到数据结构pair,这里博主自己实现了一个pair,整体代码如下:

    1. class Pair {
    2. public:
    3. Pair(string e1, int e2)
    4. :_e1(e1), _e2(e2) {}
    5. string _e1;
    6. int _e2;
    7. bool operator<(const Pair& p) const
    8. {
    9. if (_e2 != p._e2)
    10. return this->_e2 < p._e2;
    11. //此时两个出现次数相等
    12. return this->_e1 > p._e1;
    13. }
    14. };
    15. struct cmp
    16. {
    17. bool operator()(const Pair& f1, const Pair& f2)
    18. {
    19. return f1 < f2;
    20. }
    21. };
    22. class Solution {
    23. private:
    24. bool is_inArr(string s, vectorarr) {
    25. for (int i = 0; i < arr.size(); i++) {
    26. if (arr[i]._e1 == s)return true;
    27. }
    28. return false;
    29. }
    30. public:
    31. vector topKFrequent(vector& words, int k) {
    32. vectorret;
    33. unordered_mapint>hash;
    34. for (int i = 0; i < words.size(); i++) {
    35. ++hash[words[i]];
    36. }
    37. vectorarr;
    38. for (int i = 0; i < words.size(); i++) {
    39. Pair tmp(words[i], hash[words[i]]);
    40. if (!is_inArr(words[i], arr))
    41. arr.push_back(tmp);
    42. }
    43. priority_queue, cmp>pq;
    44. //初始化优先队列
    45. for (int i = 0; i < arr.size(); i++) {
    46. pq.push(arr[i]);
    47. }
    48. while (k--) {
    49. Pair tmp = pq.top();
    50. pq.pop();
    51. ret.push_back(tmp._e1);
    52. }
    53. return ret;
    54. }
    55. };

    347.前K个高频元素

    这题和上一题思路完全一样,这里直接给出代码:

    1. class Pair {
    2. public:
    3. Pair(int e1, int e2)
    4. :_e1(e1), _e2(e2) {}
    5. int _e1;
    6. int _e2;
    7. bool operator<(const Pair& p) const
    8. {
    9. if (_e2 != p._e2)
    10. return this->_e2 < p._e2;
    11. //此时两个出现次数相等
    12. return this->_e1 > p._e1;
    13. }
    14. };
    15. struct cmp
    16. {
    17. bool operator()(const Pair& f1, const Pair& f2)
    18. {
    19. return f1 < f2;
    20. }
    21. };
    22. class Solution {
    23. private:
    24. bool is_inArr(int s, vectorarr) {
    25. for (int i = 0; i < arr.size(); i++) {
    26. if (arr[i]._e1 == s)return true;
    27. }
    28. return false;
    29. }
    30. public:
    31. vector<int> topKFrequent(vector<int>& nums, int k) {
    32. vector<int>ret;
    33. unordered_map<int, int>hash;
    34. for (int i = 0; i < nums.size(); i++) {
    35. ++hash[nums[i]];
    36. }
    37. vectorarr;
    38. for (int i = 0; i < nums.size(); i++) {
    39. Pair tmp(nums[i], hash[nums[i]]);
    40. if (!is_inArr(nums[i], arr))
    41. arr.push_back(tmp);
    42. }
    43. priority_queue, cmp>pq;
    44. for (int i = 0; i < arr.size(); i++) {
    45. pq.push(arr[i]);
    46. }
    47. while (k--) {
    48. Pair tmp = pq.top();
    49. pq.pop();
    50. ret.push_back(tmp._e1);
    51. }
    52. return ret;
    53. }
    54. };

    295.数据流的中位数

    比较容易想到的思路,用一个堆,取出中间的数:

    1. class MedianFinder {
    2. private:
    3. priority_queue<int>pq;
    4. public:
    5. MedianFinder() {
    6. }
    7. void addNum(int num) {
    8. pq.push(num);
    9. }
    10. double findMedian() {
    11. priority_queue<int>pq_tmp = pq;
    12. if (pq.size() % 2 == 0) {
    13. for (int i = 0; i < pq.size() / 2 - 1; i++) {
    14. pq_tmp.pop();
    15. }
    16. //现在接下来的两个就是要用的了
    17. int num1 = pq_tmp.top();
    18. pq_tmp.pop();
    19. int num2 = pq_tmp.top();
    20. pq_tmp.pop();
    21. return (num1 + num2) / 2.0;
    22. }
    23. else {
    24. for (int i = 0; i < pq.size() / 2; i++) {
    25. pq_tmp.pop();
    26. }
    27. return pq_tmp.top();
    28. }
    29. }
    30. };

    这个版本是无法通过的,虽然用了优先队列很大程度降低了时间复杂度,但是因为中间有拷贝过程,开销还是很大的,这样提交会超时。

    用两个优先队列实现:

    直接开两个堆
    queMax记录比中位数大的 -- 是个小堆 -- 可以得到queMax的最小值
    queMin记录比中位数小的 -- 是个大堆 -- 可以得到queMin的最大值
    插入过程中保证 -- queMin的大小和queMax一样 或者queMin大小比queMax大小大1
    如果queMin过大, 把其中最大的那个数插入到queMax中去
    queMax过大同理
    如果最后queMin.size()==queMax.size() 则中位数就是两个堆顶的平均
    如果queMin.size()==queMax.size()+1 则中位数是queMin.top()

     

     

    1. class MedianFinder {
    2. public:
    3. priority_queue<int, vector<int>, less<int>> queMin;
    4. priority_queue<int, vector<int>, greater<int>> queMax;
    5. MedianFinder() {}
    6. void addNum(int num) {
    7. if (queMin.empty() || num <= queMin.top()) {
    8. queMin.push(num);
    9. if (queMax.size() + 1 < queMin.size()) {
    10. queMax.push(queMin.top());
    11. queMin.pop();
    12. }
    13. }
    14. else {
    15. queMax.push(num);
    16. if (queMax.size() > queMin.size()) {
    17. queMin.push(queMax.top());
    18. queMax.pop();
    19. }
    20. }
    21. }
    22. double findMedian() {
    23. if (queMin.size() > queMax.size()) {
    24. return queMin.top();
    25. }
    26. return (queMin.top() + queMax.top()) / 2.0;
    27. }
    28. };

    总结

    看到这里 相信大家对这几道题的解题方法已经有了一定的理解了吧?如果你感觉这篇文章对你有帮助的话,希望你可以持续关注,订阅专栏,点赞收藏都是我创作的最大动力!

    ( 转载时请注明作者和出处。未经许可,请勿用于商业用途 )
    更多文章请访问我的主页

    @背包https://blog.csdn.net/Yu_Cblog?type=blog

  • 相关阅读:
    js 数组移除指定元素【函数封装】(含对象数组移除指定元素)
    共享单车数据分析与需求预测项目
    水利行业评中级职称业绩要求有哪些?帮你分析
    PE结构学习(2)_PE结构的组成
    速览 ETHGlobal Async 黑客松决赛项目:DAO 治理隐私保护趋势涌现
    css 盒模型
    Codeforces Round #425 (Div. 2) D 题解
    Ribbon架构篇 - ZoneAvoidanceRule
    面向对象【static关键字】
    芯洲升压电源,降压电源,DC-DC,汇总
  • 原文地址:https://blog.csdn.net/Yu_Cblog/article/details/127399239