算法练习——优先级队列

ops/2025/3/5 5:18:52/

一:最后一块石头的重量

题目要求:

解题思路:

思路

创建一个优先级队列,其底层为堆结构,将数组中所有数据入堆,默认情况下为大堆。大堆创建完毕后,循环取两次堆顶元素做判断是否再次入堆,直至堆中元素小于等于1

此时出循环会有两种情况,一种情况是:

堆中没有元素,表示最后一次循环中,两个石头大小相等抵消,没有新的元素入堆

堆中有一个元素,则是题目要求的最后一块石头重量

实现代码:

class Solution {
public:int lastStoneWeight(vector<int>& stones) {priority_queue<int> pq;for(auto& s : stones){pq.push(s);}while(pq.size() > 1){int x = pq.top();pq.pop();int y = pq.top();pq.pop();if(x - y != 0) pq.push(x-y);}return pq.size() ? pq.top() : 0;}
};

二:数据流中第K大的数

题目要求:

解题思路:

思路

这类问题统称为Top_K问题

对于判断第K大或者前K大,都是建立小堆

对于第K大,我们就创立个数为K个的小堆,堆顶即为第K大

对于前K大,我们只要创立个数为K的小堆,然后去遍历数组,将满足结果的入堆,然后出堆,维护这个堆即可

对于判断第K小或者前K小,都是建立大堆。

对于第K小,我们就创立个数为K的大堆,堆顶即为第K小

对于前K小,我们只需创立个数为K的大堆,然后遍历数组,在遍历的过程去维护大堆即可

实现代码:

class KthLargest {
public:KthLargest(int k, vector<int>& nums) :_k(k){for(auto& n : nums){_heap.push(n);if(_heap.size() > _k) _heap.pop();}}int add(int val) {_heap.push(val);if(_heap.size() > _k) _heap.pop();return _heap.top();}priority_queue<int,vector<int>,greater<int>> _heap;int _k;
};/*** Your KthLargest object will be instantiated and called as such:* KthLargest* obj = new KthLargest(k, nums);* int param_1 = obj->add(val);*/

三:前K个高频单词

题目要求:

解题思路:

思路

借助哈希表统计每个单词出现的个数,并记录于 unordered_map<string, int> hash; 中

和上一题类似,本题也属于Top_K问题中,前K个大一类,因此我们需要创建一个堆中数据个数为K的小堆,然后遍历哈希表来维护这个小堆。具体做法为:若比堆顶数据大,则入堆,若堆中数据个数大于K,则出堆。

实现代码:

class Solution {
public:struct Com{bool operator()(const pair<string,int>& x1, const pair<string,int>& x2){return x1.second > x2.second || (x1.second == x2.second && x1.first < x2.first);}};vector<string> topKFrequent(vector<string>& words, int k) {unordered_map<string,int> hash;for(auto& str : words){hash[str]++;}priority_queue<pair<string,int>,vector<pair<string,int>>,Com> heap;for(auto& str : hash){heap.push(str);if(heap.size() > k) heap.pop();}vector<string> ret;while(heap.size()){ret.emplace_back(heap.top().first);heap.pop();}reverse(ret.begin(),ret.end());return ret;}
};

四:数据流中的中位数

题目要求:

解题思路:

思路:如果要找寻有序数据中的中位数,比较好的做法是:建立一个大堆和小堆来维护这组数据。

假设这组数从左到右依次按顺序排列

我们将数据分成两段来看,前一段为较小的数,这段数建立大堆,因此堆顶恰好是这组数中最大的值,维持大堆的数据个数为m

后一段为较大的数,这段建立小堆,因此堆顶恰好是这组数中最小的值,维持小堆的数据个数为n

当m = n 时: 中位数恰好是(大堆堆顶+小堆堆顶)/ 2

当m = n+1,即大堆个数比小堆多一个时,中位数恰好是 大堆堆顶元素

因此我们在遍历数组arr时,需要保证m == n 或者 m == n+1

遍历原数组arr(假设当前值为num):

①当 m = n 时,先判空

Ⅰ:若 m.top() >= num; num 入左边大堆,此时 m == n + 1;

Ⅱ:否则入右边小堆,此时 m != n + 1; 为了维护 m = n+1,需将右边小堆堆顶元素入左边大堆(右边小堆保证了堆顶元素为较小值),然后右边小堆在出堆(维护 m = n+1)

②当 m = n + 1时:

Ⅰ:若 m.top() < num; num 入右边小堆,此时 m == n ;

Ⅱ:否则入左边大堆,此时 m != n + 1; 为了维护 m = n+1,需将左边大堆堆顶元素入右边小堆(左边大堆保证了堆顶元素为较大值),然后左边大堆在出堆(维护 m = n)

实现代码:

class MedianFinder {
public:MedianFinder() {}void addNum(int num) {if(_left.size() == _right.size()){if(_left.size() == 0 || _left.top() >= num) _left.push(num);else if (_right.size() == 0 || _left.top() < num) {_right.push(num);_left.push(_right.top());_right.pop();}}else{if(_left.top() < num) _right.push(num);else {_left.push(num);_right.push(_left.top());_left.pop();}}}double findMedian() {if(_right.size() == _left.size())   return (_right.top() + _left.top()) / 2.0;else return _left.top();}
private:priority_queue<int> _left;priority_queue<int,vector<int>,greater<int>> _right;
};/*** Your MedianFinder object will be instantiated and called as such:* MedianFinder* obj = new MedianFinder();* obj->addNum(num);* double param_2 = obj->findMedian();*/


 


http://www.ppmy.cn/ops/163223.html

相关文章

探秘基带算法:从原理到5G时代的通信变革【四】Polar 编解码(一)

文章目录 2.3 Polar 编解码2.3.1 Polar 码简介与发展背景2.3.2 信道极化理论基础对称容量与巴氏参数对称容量 I ( W ) I(W) I(W)巴氏参数 Z ( W ) Z(W) Z(W)常见信道信道联合信道分裂信道极化 本博客为系列博客&#xff0c;主要讲解各基带算法的原理与应用&#xff0c;包括&…

MR30系列分布式I/O:高稳定与高精准赋能锂电池覆膜工艺革新

在新能源行业高速发展的背景下&#xff0c;锂电池生产工艺对自动化控制的精准性和可靠性提出了更高要求。作为锂电池生产中的关键环节&#xff0c;覆膜工艺直接关系到电池的绝缘性能、安全性及使用寿命。面对复杂的工艺控制需求&#xff0c;明达技术MR30系列分布式I/O模块凭借其…

STM32之影子寄存器

预分频寄存器计数到一半的时候&#xff0c;改变预分频值&#xff0c;此时不会立即生效&#xff0c;会等到计数完成&#xff0c;再从影子寄存器即预分频缓冲器里装载修改的预分频值。 如上图&#xff0c;第一行是内部时钟72M&#xff0c;第二行是时钟使能&#xff0c;高电平启动…

Ubuntu 20.04下配置VSCode以支持OpenCV库开发

Ubuntu 20.04下配置VSCode以支持OpenCV库开发 1. 安装OpenCV库安装OpenCV&#xff08;推荐使用APT安装&#xff09;或者从源码安装OpenCV&#xff08;可选&#xff09; 2. 安装VSCode的C扩展3. 配置c_cpp_properties.json4. 编写代码并测试5. 配置tasks.json&#xff08;编译Op…

【PyQt5项目实战分享】基于YOLOv5的交通道路目标检测和数据分析软件

这是我之前用PyQt5做的一个基于YOLOv5的交通目标检测软件&#xff0c;包括物体检测和相关数据的分析功能&#xff0c;最近将其完善了下并打包&#xff0c;希望对大家有所帮助~ Tips&#xff1a;文末有我放到 github 和 gitee 的项目开源地址哦 文章目录 ⭐项目功能交通物体检测…

element-push el-date-picker日期时间选择器,禁用可选中的时间 精确到分钟

效果 本来用的是时间段&#xff0c;但是甲方说不好用&#xff0c;让换成这样的 六百六十六 <el-form-item label"考评时间" class"is-required"><div style"display: flex; gap: 10px;"><el-form-item label"" style&…

flutter-制作淡入淡出的Banner切换Fade效果

文章目录 1. 介绍2. 例子 1. 介绍 本节主要介绍如何制作一个淡入淡出的 Fade 过渡 Banner 切换。Fade 过渡通常指的是当元素&#xff08;如图片、文本框等&#xff09;显示或隐藏时&#xff0c;元素的透明度会逐渐变化&#xff0c;从而实现平滑的视觉过渡效果。这种效果可以提…

C#中使用Newtonsoft.Json多态正反序列化

一、在通讯中&#xff0c;使用json字符串作为命令进行传递&#xff0c;发送接收方都需要序列化。 常见方法有两种&#xff0c; 1&#xff09;使用TypeNameHandling TypeNameHandling.All &#xff0c;但是这种序列化的内容中包含命令空间信息&#xff0c;这种不利于两个应用…