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

算法_优先级队列---持续更新

文章目录

  • 前言
  • 最后一块石头重量
    • 题目要求
    • 题目解析
    • 代码如下
  • 数据流中的第K大元素
    • 题目要求
    • 题目解析
    • 代码如下
  • 前K个高频单词
    • 题目要求
    • 题目解析
    • 代码如下
  • 数据流的中位数
    • 题目要求
    • 题目解析
    • 代码如下

前言

本文将会向你分享优先级队列相关的题目:最后一块石头重量、数据流中的第K大元素、前K个高频单词、数据流的中位数

最后一块石头重量

https://leetcode.cn/problems/last-stone-weight/

题目要求

在这里插入图片描述

题目解析

题目要求每次从一堆数中找出最大的两个,然后再进一步判断,最重要的是如何从一堆数中找出最大的数,这时可以想到用大根堆,最大的在堆顶,pop堆顶,就可以拿到次大的了。

代码如下

class Solution {
public:
    int lastStoneWeight(vector<int>& stones) 
    {
        priority_queue<int> heap;   //优先级队列,默认是一个大根堆
        for(auto& e : stones)
        {
            heap.push(e);
        }
        while(heap.size() > 1)
        {
            int x = heap.top(); heap.pop();
            int y = heap.top(); heap.pop();
            if(x > y) heap.push(x - y);
        }
        return heap.size() ? heap.top() : 0;
    }
};

数据流中的第K大元素

https://leetcode.cn/problems/jBjn9C/

题目要求

在这里插入图片描述

题目解析

题目要求是找到数据流中的第K大元素,那么把这些数据放到一个小根堆中就可以解决,题目有点绕(将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素),其实就是外部调用add函数传入的val 有数据流1,2,3,4。比如需要求第3(K)大的元素,我们知道是2,只需要将小根堆的元素个数维持为3(K)个,那么堆顶元素就是我们需要求的第3大的元素。 也就是当堆里的元素大于K,就pop,这样就能维持堆里的元素等于K

在这里插入图片描述
在这里插入图片描述

代码如下

class KthLargest {
public:
    priority_queue<int, vector<int>, greater<int>> heap;
    int k = 0;
    KthLargest(int k, vector<int>& nums) 
    {
        this->k = k;
        for(auto& e : nums)
        {
            add(e);
        }
    }
    //确保堆始终包含k个最大的元素,堆顶将是第k大的元素
    int add(int val) 
    {
        heap.push(val);
        if (heap.size() > k) {  
            heap.pop();  
        }  
        return heap.top();
    }
};

/**
 * Your KthLargest object will be instantiated and called as such:
 * KthLargest* obj = new KthLargest(k, nums);
 * int param_1 = obj->add(val);
 */

前K个高频单词

https://leetcode.cn/problems/top-k-frequent-words/

题目要求

在这里插入图片描述

题目解析

题目要求返回前k个出现次数最多的单词,那么很容易想到的是建一个小堆,维持小堆的个数未为k个,堆里剩下的就是次数出现最多的,但是题目中有额外要求,如果单词出现的频次相同,那么就按字典顺序排序。那么我们是需要自定义比较函数的

当second(频次)相同,那么按照字典序排序,也就是小的排在前面,a.first < b.first也就是小的排在前面, a.second > b.second频次大的排在后面

在这里插入图片描述

if(a.second == b.second)
{   
    return a.first < b.first;   //按照字典顺序排序
}
else return a.second > b.second;   

代码如下

class Solution {
public:
    struct cmp
    {
        bool operator()(const pair<string, int>& a, const pair<string, int>& b)
        {
            //单词出现的频率相同
            if(a.second == b.second)
            {   
                return a.first < b.first;   //按照字典顺序排序
            }
            else return a.second > b.second;    //小根堆,大的排在下面
        }
    };
    vector<string> topKFrequent(vector<string>& words, int k) 
    {
        unordered_map<string, int> hash;    //用哈希表统计单词次数
        for(auto& e : words)
        {
            hash[e]++;
        }
        //TopK,取前k个出现次数最多的单词
        priority_queue<pair<string, int>, vector<pair<string, int>>, cmp> heap;
        for(auto& e : hash)
        {
            heap.push(e);
            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;
    }
};

数据流的中位数

https://leetcode.cn/problems/find-median-from-data-stream/

题目要求

在这里插入图片描述

题目解析

题目要求实现中位数查找器,直接利用数组的个数/2来求中位数的方式是不够高效的,因为数据流是动态变化的。

这里可以用一个大小堆,小堆中的元素每个都比大堆中的元素大,每当数据来的时候,判断与大小堆顶的关系,插入到对应的堆中,需要注意的是还要维持大小堆中的元素个数,只有maxHeap,size() = minHeap.size() 或者 maxHeap,size() = minHeap.size()+1只有这两种情况才行。因为只有这样,如果数据流的元素个数为奇数,那么就是大堆堆顶,如果是偶数,就手动求一下(大堆堆顶+小堆堆顶)/2即可

ps:这种方法并不好想,这次记住就行啦!

在这里插入图片描述

代码如下

class MedianFinder {
public:
    MedianFinder() 
    {}
    
    void addNum(int num) 
    {
        int sz1 = maxHeap.size(), sz2 = minHeap.size();
        if(sz1 == sz2)
        {
            if(sz1 == 0 || num <= maxHeap.top())   //注意sz1 == 0要放到最前面,否则当堆中元素为空时,会空指针
                maxHeap.push(num); //直接插入
            else
            {
                minHeap.push(num); //此时sz2 == sz1 + 1
                int tmp = minHeap.top(); minHeap.pop();
                maxHeap.push(tmp);
            }
        }
        else    //sz1 == sz2+1
        {
            if(num <= maxHeap.top())
            {
                maxHeap.push(num);
                int tmp = maxHeap.top(); maxHeap.pop();
                minHeap.push(tmp);  //维持sz1 == sz2+1
            }
            else
            {
                minHeap.push(num);  //直接插入
            }
        }
    }
    
    double findMedian() 
    {
        if((maxHeap.size() + minHeap.size()) % 2 == 0)        
            return static_cast<double>(maxHeap.top() + minHeap.top()) / 2;
        else 
            return static_cast<double>(maxHeap.top());
    }
public:
    priority_queue<int, vector<int>, greater<int>> minHeap;
    priority_queue<int> maxHeap;
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder* obj = new MedianFinder();
 * obj->addNum(num);
 * double param_2 = obj->findMedian();
 */

http://www.kler.cn/a/305870.html

相关文章:

  • UAC2.0 speaker——同时支持 16bit,24bit 和 32bit
  • 操作系统lab4-页面置换算法的模拟
  • AUTOSAR_EXP_ARAComAPI的7章笔记(3)
  • Vector 深度复制记录
  • 字符及字符串(ASCII编码系统)
  • 【日志】392.判断子序列
  • mysql组合键唯一
  • HTTP 四、HttpClient的使用
  • 一文带你全面了解RAID技术:从基础到进阶的全景解析
  • 大厂硬件梦:字节、腾讯“向首”,华为、小米“向手”
  • 设计模式之建造者模式(通俗易懂--代码辅助理解【Java版】)
  • MSYS vs MSYS2:功能、兼容性与易用性全面比拼,助你挑选最佳Windows开发伴侣
  • SpringBoot集成Thymeleaf模板引擎,为什么使用(详细介绍)
  • 【CSS in Depth 2 精译_031】5.3 Grid 网格布局的两种替代语法
  • TCP Analysis Flags 之 TCP ZeroWindow
  • 【机器学习】7 ——k近邻算法
  • npm install报错,gyp verb `which` failed Error: not found: python
  • 第十六节:学习Springboot 的自定义资源路径(自学Spring boot 3.x的第四天)
  • 鸿蒙之Hello Word 遇坑总结 mac系统 不能预览 提示 Only files in a module can be previewed 解决办法
  • [Mdp] lc3290. 最高乘法得分(二维dp+状态定义+状态转移+LCS问题+好题+周赛415_2)
  • 网络原理(3)—— 应用层、传输层(TCP)
  • ArcGIS Pro SDK (十三)地图创作 4 设备
  • Qt 学习第十天:标准对话框 页面布局
  • Windows11 WSL2的ubuntu 22.04中拉取镜像报错
  • 分贝转换 1 mVpp = 9.03dBmV
  • 【软考】设计模式之抽象工厂模式