【算法】使用优先级队列(堆)解决算法题(TopK等)(C++)

文章目录

  • 1. 前言
  • 2. 算法题
    • 1046.最后一块石头的重量
    • 703.数据流中的第K大元素
  • 2.5 如何选择大根堆 与 小根堆? + 为什么选择大根堆(小根堆)?
    • 692.前K个高频单词
    • 295.数据流的中位数

1. 前言

我们知道:优先级队列是一种常用的数据结构,用于解决许多算法问题。基于堆(Heap)实现,在每次操作中能够快速找到最大或最小值

使用优先级队列的典型算法问题包括:

  • Top K 问题:查找列表中前 K 个最大或最小的元素。
  • 合并 K 个排序数组:将 K 个已排序的数组合并为一个有序数组。
  • Dijkstra 算法:在加权图中找到从起点到目标节点的最短路径。
  • Huffman 编码:使用最小堆构建前缀编码树来压缩数据。

下面会挑选一些算法题并使用优先级队列进行解题。


2. 算法题

1046.最后一块石头的重量

在这里插入图片描述
思路

  • 解法大根堆
  • 大根堆:每个节点都大于等于其子节点,则堆顶节点为最大的
    1. 将数组中所有元素加入堆中,并进行循环,直至堆为空
    2. 循环每次 取两次堆顶元素,即当前最重的两石头
    3. 将两元素差继续入堆,重复过程直至循环结束
      • 如果堆中还剩一个元素,返回该元素
      • 如果已经没有元素,返回0

代码

int lastStoneWeight(vector<int>& stones) {priority_queue<int> heap; // 创建大根堆// 将数组所有元素添加到堆中for(int stone : stones) heap.push(stone);while(heap.size() > 1){// 每次取最大的两个数int a = heap.top(); heap.pop();int b = heap.top(); heap.pop();if(a > b) heap.push(a - b);}return heap.size() ? heap.top() : 0;
}

703.数据流中的第K大元素

在这里插入图片描述

思路

  • 题意分析:根据题目,可以看出来该题是一道topK类型题
  • 解法全局变量 + 小根堆
    • 使用全局变量可以省去函数之间传参的过程,也方便编写代码
    1. 创建全局变量标记k和创建全局小根堆
      • 关于为什么选择小根堆,可以看后面的解释。
    2. 由于add函数要求添加数字后返回第k大的元素,对于构造函数KthLargest,我们直接将数组中前k大的元素插入
    3. 对于add函数,直接将val插入到堆中并判断是否堆内元素超出k个
      • 如果超出,则pop掉,后直接返回堆顶元素(即为第K大)

2.5 如何选择大根堆 与 小根堆? + 为什么选择大根堆(小根堆)?

在这里插入图片描述

代码

class KthLargest {
public:// 小根堆priority_queue<int, vector<int>, greater<int>> heap;int _k;KthLargest(int k, vector<int>& nums) {_k = k;for(int num : nums){heap.push(num);if(heap.size() > _k) heap.pop();} }int add(int val) {heap.push(val);if(heap.size() > _k) heap.pop();return heap.top();}
};

692.前K个高频单词

在这里插入图片描述

思路

  • 题意分析:即返回数组中出现次数最多的字符串(单词)
  • 解法哈希表 + 优先级队列
    1. 哈希表统计每个单词的出现次数
    2. 根据题目要求,当单词的频率相同时,按照字典序排列,则我们自定义优先级队列的比较函数。则:
      • 当单词频率不同时,用小堆的比较方式
      • 当单词频率相同时,按照字典序,用大堆的比较方式
    3. 将哈希表中统计的前k高的 字母以及频率 加入到队列
    4. 最后返回结果,遍历堆,每次加入到结果集result中并pop即可。

代码

vector<string> topKFrequent(vector<string>& words, int k) {// 统计单词出现频率unordered_map<string, int> freq;for (const string& word : words) {freq[word]++;}// 自定义优先队列的比较函数auto cmp = [](const pair<string, int>& a, const pair<string, int>& b) {// 比较出现次数,如果相同则按照字母顺序return a.second > b.second || (a.second == b.second && a.first < b.first);};// 优先队列,默认是大顶堆,用于存储频率最高的 k 个单词priority_queue<pair<string, int>, vector<pair<string, int>>, decltype(cmp)> pq(cmp);// 遍历统计好的频率,将单词加入优先队列for (const auto& entry : freq) {pq.push(entry);if (pq.size() > k) {pq.pop(); // 如果队列大小超过 k,则弹出频率最小的单词}}// 从优先队列中取出结果vector<string> result(k);for (int i = k - 1; i >= 0; --i) {result[i] = pq.top().first; // 逆序存储结果pq.pop();}return result;
}

295.数据流的中位数

在这里插入图片描述

思路

  • 题意分析:题目要求实现一个类,类中包含一个构造函数、一个add函数用于添加元素、以及一个find函数

  • 解法一排序 sort
    在这里插入图片描述

    • 对于本题,使用该排序法是会超时的
  • 解法二插入排序的思想
    在这里插入图片描述

    • 插入排序思想解本题是有可能超时的,但依然需要了解这种解题思想。
  • 解法三大小堆维护
    在这里插入图片描述
    在这里插入图片描述

    • 上图解释了方法思路,具体细节看下面代码即可。

代码

class MedianFinder {
public:// 大小堆,左大堆,右小堆// 且当共有奇数个元素时,左存多一个元素priority_queue<int, vector<int>> left;priority_queue<int, vector<int>, greater<int>> right;MedianFinder() {} // 构造void addNum(int num) {if(left.size() == right.size()){   if(left.empty() || 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() {return (left.size() == right.size()) ? (left.top() + right.top()) / 2.0 : left.top();}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/634326.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Maven 基础安装配置及使用

大家好我是苏麟 , 今天聊聊Maven . Maven Maven , 是Apache公司下基于Java开发的开源项目 . 我们构建一个项目需要用到很多第三方的类库&#xff0c;需要引入大量的jar包。一个项目Jar包的数量之多往往让我们瞠目结舌&#xff0c;并且Jar包之间的关系错综复杂&#xff0c;一…

高并发缓存问题分析以及分布式锁的实现

一,场景概述: 在高并发的环境下,比如淘宝,京东不定时的促销活动,大量的用户访问会导致数据库的性能下降,进而有可能数据库宕机从而不能产生正常的服务,一般一个系统最大的性能瓶颈&#xff0c;就是数据库的io操作,如果发生大量的io那么他的问题也会随之而来。从数据库入手也是…

Python | 六、哈希表 Hash Table(列表、集合、映射)

哈希表基础 哈希表是一类数据结构&#xff08;哈希表包含数组、集合和映射&#xff0c;和前两篇文章叙述的字符串、链表平级&#xff09;哈希表概念&#xff1a;类似于Python里的字典类型&#xff0c;哈希表把关键码key值通过哈希函数来和哈希表上的索引对应起来&#xff0c;之…

力扣第236题——二叉树的最近公共祖先 (C语言题解)

题目描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以…

【论文总结】基于深度学习的特征点提取,特征点检测的方法总结

这里写目录标题 相关工作1. Discriminative Learning of Deep Convolutional Feature Point Descriptors(2015)网络结构sift算法损失函数的构建 2.MatchNet(2015)网络中的组成部分其他组成部分损失函数结果 3.LIFT: Learned Invariant Feature Transform(2016)网络结构训练网络…

虚拟线程探索与实践

优质博文&#xff1a;IT-BLOG-CN 一、简介 虚拟线程是轻量级线程&#xff0c;极大地减少了编写、维护和观察高吞吐量并发应用的工作量。虚拟线程是由JEP 425提出的预览功能&#xff0c;并在JDK 19中发布&#xff0c;JDK 21中最终确定虚拟线程&#xff0c;以下是根据开发者反馈…

【LeetCode每日一题】2171. 拿出最少数目的魔法豆

2024-1-18 文章目录 [2171. 拿出最少数目的魔法豆](https://leetcode.cn/problems/removing-minimum-number-of-magic-beans/)思路&#xff1a; 2171. 拿出最少数目的魔法豆 思路&#xff1a; 对输入的数组进行排序&#xff0c;使得数组中的元素按照升序排列。初始化一个变量s…

SQL注入实战操作

一&#xff1a;SQl注入分类 按照注入的网页功能类型分类&#xff1a; 1、登入注入&#xff1a;表单&#xff0c;如登入表单&#xff0c;注册表单 2、cms注入&#xff1a;CMS逻辑:index.php首页展示内容&#xff0c;具有文章列表(链接具有文章id)、articles.php文 章详细页&a…

阿里云腾讯七牛内容安全配置

一&#xff0c;阿里云 1&#xff0c;配置RAM角色权限 向RAM用户授权系统策略权限&#xff1a;AliyunYundunGreenWebFullAccess 2&#xff0c;内容安全控制台——授权访问OSS 不授权——会报错——no permission(not authorized about role AliyunCIPScanOSSRole)

Linux 【C编程】 引入线程,线程相关函数

1.线程的引入 1.1使用线程同时读取键盘和鼠标 代码演示&#xff1a; #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <unistd.h> #include <termios.h> #include <fcntl.h> #include <string.h> // 读取…

前端面试题(持续更新~~)

文章目录 一、基础1、数组常用的方法2、数组有哪几种循环方式&#xff1f;分别有什么作用&#xff1f;3、字符串常用的方法4、原型链5、闭包6、常见的继承7、cookie 、localstorage 、 sessionstrorage区别8、数组去重方法9、http 的请求方式10、数据类型的判断方法11、cookie …

性能压力测试:企业成功的关键要素

性能压力测试在现代企业软件开发中扮演着至关重要的角色&#xff0c;它不仅仅是一项技术手段&#xff0c;更是保障企业成功的关键要素。本文将探讨性能压力测试在企业中的重要性&#xff0c;并阐述其对业务稳定性、用户体验和品牌声誉的影响。 一、保障业务稳定性 1、应对高负载…

使用zabbix-proxy进行分布式监控

目录 一、准备4台服务器 二、配置主从复制 1.准备环境 2.主机名解析 3.安装数据库 4.配置主库db1 5.配置从库db2 6.主从状态显示 三、db1&#xff0c;db2配置zabbix-agent 三、zabbix-server的配置 四、zabbix-proxy的配置 1.为您的平台安装和配置Zabbix-proxy a. …

操作教程|JumpServer堡垒机结合Ansible进行批量系统初始化

运维人员常常需要对资产进行系统初始化的操作&#xff0c;而初始化服务器又是一项繁琐的工作&#xff0c;需要花费运维人员大量的时间和精力。为了提高效率&#xff0c;许多组织会使用自动化工具和脚本来简化这些任务。自动化工具的运用可以大幅降低运维人员的工作量&#xff0…

Redis实战之-分布式锁

一、基本原理和实现方式对比 分布式锁&#xff1a;满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁&#xff0c;只要大家使用的是同一把锁&#xff0c;那么我们就能锁住线程&#xff0c;不让线程进行&#xff0c;让程序串行…

档案数字化如何选择合适的扫描仪

选择合适的扫描仪是进行档案数字化的关键步骤。以下是一些选择合适扫描仪的要点&#xff1a; 1. 扫描速度&#xff1a;选择具有合适的扫描速度的扫描仪&#xff0c;以便能够快速处理大量的文件。 2. 扫描分辨率&#xff1a;扫描分辨率决定了扫描后图像的清晰度。对于大多数文档…

RIP基础实验配置

要使用RIP完成以上命令需求 1&#xff0c;首先划分ip地址 有图可见有四个网段需要划分 192.168.1.0/26 192.168.3.0/26 192.168.7.0/26 192.168.5.0/26 给两个骨干网段&#xff0c;给两个环回接口&#xff0c;由下图所示&#xff1a; 其次&#xff0c;规划好ip后在各个接口…

v-if和v-for哪个优先级更高?

v-if和v-for哪个优先级更高&#xff1f; 结论&#xff1a; vue2输出的渲染函数是先执行循环&#xff0c;在看条件判断&#xff0c;如果将v-if和v-for写在一个标签内&#xff0c;哪怕只渲染列表中的一小部分&#xff0c;也要重新遍历整个列表&#xff0c;无形造成资源浪费。vu…

DolphinDB 与盈米基金达成战略合作,打造领先的资管机构投顾解决方案

1月16日上午&#xff0c;DolphinDB 与盈米基金在上海签署战略合作协议&#xff0c;共同开启专业资管投顾投研合作新篇章。 DolphinDB 联合创始人、COO 初阳春与盈米基金副总裁、研究院院长杨媛春出席仪式&#xff0c;并代表双方完成签约。 打造市场领先的资管机构投顾服务 盈…

浅析Redis①:命令处理核心源码分析(上)

写在前面 Redis作为我们日常工作中最常使用的缓存数据库&#xff0c;其重要性不言而喻&#xff0c;作为普调开发者&#xff0c;我们在日常开发中使用Redis&#xff0c;主要聚焦于Redis的基层数据结构的命令使用&#xff0c;很少会有人对Redis的内部实现机制进行了解&#xff0c…