栈和队列-优先级队列/堆

题目链接:347. 前 K 个高频元素 - 力扣(LeetCode)

// 时间复杂度:O(nlogk)
// 空间复杂度:O(n)
class Solution {
public:
    //使用小顶堆,将前面的pop,剩下的K个就是频率最高的k个
    //不使用大顶堆的原因是每次加入新元素时要将堆顶元素pop,则会将频率最高的元素pop

    //仿函数(Functor)
    //仿函数类都必须重载()运算符
    //例如下面的类,在对其进行实例化时调用其构造函数,此时就会执行重载后的()函数体
    //具体在优先级队列中时怎么执行的不看源码不清楚
    class mycomparison{//表示频率小的优先级大
    public:
        //为什么要重载()啊?不懂
        bool operator()(const pair<int,int> &lhs, const pair<int,int> &rhs){
            return lhs.second>rhs.second;
        }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        //统计每个元素的频率
        unordered_map<int,int> map;
        for(int i=0;i<nums.size();i++)
        {
            map[nums[i]]++;
        }
        
        //优先级队列priority_queue:保证每次的队首元素都是优先级最大的
        //底层是通过堆来实现的

        //定义一个小顶堆
        priority_queue<pair<int,int>,vector<pair<int,int>>,mycomparison> pri_que;
        //遍历map,将键值对放入优先级队列
        for(auto it:map)
        {
            pri_que.push(it);
            if(pri_que.size()>k)//保持优先级队列中始终为当前频率最高的前k个元素
            {
                pri_que.pop();
            }
        }

        //最后小顶堆中剩余的K个元素即频率最高的前k个元素
        vector<int> res;
        while(!pri_que.empty())
        {
            res.push_back(pri_que.top().first);
            pri_que.pop();
        }
        return res;
    }
};

题目链接:692. 前K个高频单词 - 力扣(LeetCode)

class Solution {
public:
    class mycomparison{
    public:
        bool operator()(const pair<string,int> &l,const pair<string ,int> &r)
        {
            //按字典顺序是当两个频率相等时,对first进行排序
            //按字典顺序要倒序,因为这是小顶堆
            return l.second==r.second?l.first<r.first:l.second>r.second;
        }
    };
    vector<string> topKFrequent(vector<string>& words, int k) {
        //统计单词频率
        unordered_map<string,int> m;
        for(auto str:words)
        {
            m[str]++;
        }

        //建立小顶堆
        priority_queue<pair<string,int>,vector<pair<string,int>>,mycomparison> smallTopPile;
        //遍历map,将其全部元素push进小顶堆
        for(auto it:m)
        {
            smallTopPile.push(it);
            if(smallTopPile.size()>k)//保证小顶堆中始终是前K个频率最高的元素
            {
                smallTopPile.pop();
            }
        }

        //这里注意,在输出结果时是要倒序输出的!
        vector<string> res(k);
        int i=k-1;
        while(!smallTopPile.empty())
        {
            res[i]=smallTopPile.top().first;
            smallTopPile.pop();
            i--;
        }
        return res;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值