C++算法:优先级队列

优先级队列

1.最后一块石头的重量

使用优先级队列模拟即可。

cpp 复制代码
class Solution {
public:
    int lastStoneWeight(vector<int>& stones)
    {
        priority_queue<int> pq;
        for (int& e : stones)
            pq.push(e);
        while (pq.size() > 1)
        {
            int x = pq.top();
            pq.pop();
            int y = pq.top();
            pq.pop();
            if (x > y)
                pq.push(x - y);
        }
        return pq.size() ? pq.top() : 0;
    }
};

2. * TopK:数据流中的第K大元素

这道题其实就是TopK问题。TOP-K问题即求数据集合中前K个或第K大最大的元素或者最小的元素,一般情况下数据量都比较大。如果数据量大,不能使用排序解决,因为可能数据不能一次全部加载到内存,排序算法的空间消耗也会很大。

往往是用堆来解决TopK问题。求第K大的元素,创建小堆,控制堆的大小不超过K,把数据集合的元素入堆。当堆的大小为K时,新元素入堆,此时堆的大小为K+1,堆顶元素是这K+1个元素中最小的,即目前第K+1大的元素,此时pop,堆顶元素就是目前第K大的元素。如此遍历数据集合,就能得到前K个最大元素,堆顶为第K大元素。时间复杂度为O(N*logK)。

cpp 复制代码
class KthLargest {
    priority_queue<int, vector<int>, greater<int>> heap;
    int _k;
public:
    KthLargest(int k, vector<int>& nums)
    {
        _k = k;
        for (int e : nums)
        {
            heap.push(e);
            if (heap.size() > _k)
                heap.pop();
        }
    }

    int add(int val)
    {
        heap.push(val);
        if (heap.size() > _k)
            heap.pop();
        return heap.top();
    }
};

3. * TopK:前K个高频单词

用unordered_map或map统计单词出现频次;创建大小为k的堆,频次不同时满足小根堆,频次相同时,按照字典序,应满足大根堆;得到符合要求的前k个单词后,堆顶元素是频次小,字典序大,所以应该从ret数组尾部开始放元素,否则从头开始放元素后逆置数组。

cpp 复制代码
class Solution
{
    typedef pair<string, int> PSI;
    struct Greater
    {
        bool operator()(const PSI& p1, const PSI& p2)
        {
            if (p1.second == p2.second)
                return p1.first < p2.first;
            return p1.second > p2.second;
        }
    };
public:
    vector<string> topKFrequent(vector<string>& words, int k)
    {
        //统计单词频次
        map<string, int> m;
        for (string& e : words)
            m[e]++;
        
        //TopK
        priority_queue<PSI, vector<PSI>, Greater> heap;
        for (const PSI& psi : m)
        {
            heap.push(psi);
            if (heap.size() > k)
                heap.pop();
        }
        
        //提取结果
        vector<string> ret(k);
        for (int i = k - 1;i >= 0;i--)
        {
            ret[i] = heap.top().first;
            heap.pop();
        }
        return ret;
    }
};

4.数据流的中位数

利用大小堆解决。假设数据有序,数据中位数左边用大根堆left维护,右边用小根堆right维护。

如果m == n,则中位数为(left.top()+right.top())/2;如果m>n,即m == n+1,则中位数为left.top()。

每次add()时,对于新加入的数据num,如果m == n,当m为0或num<=left.top()时,直接进left;当num>left.top()时,num进right,此时m<n,再把right.top()放入left中,保持m == n。

如果m>n,当num>=left.top()时,则num直接进right;当num<left.top()时,num进left,此时m == n+2,再把left.top()放入right中保持 m == n+1。

cpp 复制代码
class MedianFinder
{
    priority_queue<int, vector<int>, less<int>> left;
    priority_queue<int, vector<int>, greater<int>> right;
public:
    MedianFinder()
    {
    }

    void addNum(int num)
    {
        int m = left.size(), n = right.size();

        if (m == n)
        {
            if (m == 0 || num <= left.top())
                left.push(num);
            else
            {
                right.push(num);
                left.push(right.top());
                right.pop();
            }
        }
        else
        {
            if (num < left.top())
            {
                left.push(num);
                right.push(left.top());
                left.pop();
            }
            else
                right.push(num);
        }
    }

    double findMedian()
    {
        int m = left.size(), n = right.size();
        if (m != n)
            return left.top();
        else
            return (left.top() + right.top()) / 2.0;
    }
};
相关推荐
weixin_4241836135 分钟前
开放—封闭原则实战(下):基于策略的流程编排与编译期多态
c++·分布式·系统架构
wuminyu1 小时前
C++协程实现接收端的零拷贝Buffer管理原理剖析
java·linux·c语言·jvm·c++
小蒋学算法1 小时前
算法-交替删除操作后最后剩下的整数-跟着灵茶山艾府学算法
数据结构·算法
m0_380743871 小时前
C++中的freopen的用法实例详解
开发语言·c++
荆棘鸟智能2 小时前
林业遥感长势评估怎么做?从NDVI时序分析到LiDAR蓄积量回归
人工智能·算法·智慧林业
Escalating_xu2 小时前
【Python】基础语法(1):常量、变量、类型、输入输出与运算符
开发语言·python
jimy12 小时前
polymorph.cpp里面的“析构函数、智能指针”问题
开发语言·c++
m0_380743872 小时前
PHP 8.3 缓存清除不生效怎么排查
开发语言·php
hhb_6182 小时前
AIRAGDebug:一键定位RAG链路异常
人工智能·python·算法
朝朝辞暮i3 小时前
C++ 第 6 课:switch —— 多状态选择
开发语言·c++·算法