【优选算法 | 优先级队列】从堆实现到解题框架:彻底搞懂优先级队列

【优选算法 | 优先级队列】从堆实现到解题框架:彻底搞懂优先级队列
在这里插入图片描述
算法相关知识点可以通过点击以下链接进行学习一起加油!
双指针滑动窗口二分查找前缀和位运算
模拟链表哈希表字符串模拟栈模拟(非单调栈)
优先级队列(Priority Queue),本质上是一个支持动态插入与按优先级弹出操作的堆结构,是处理这类问题的强力工具。
本文将从底层的堆实现出发,逐步构建出优先级队列的完整解题框架,并结合高频
题目,帮助你真正掌握它在算法实战中的运用。
请添加图片描述
Alt

🌈个人主页:是店小二呀
🌈C/C++专栏:C语言\ C++
🌈初/高阶数据结构专栏: 初阶数据结构\ 高阶数据结构
🌈Linux专栏: Linux
🌈算法专栏:算法
🌈Mysql专栏:Mysql

🌈你可知:无人扶我青云志 我自踏雪至山巅

请添加图片描述

文章目录

本专题利用优先级队列来解决问题。为此,我们首先需要了解如何使用快速选择算法来解决 Tok 问题,并掌握大根堆与小根堆的适用场景及选择依据。

在这里插入图片描述

一、铺垫知识

1.1 堆排序(Heap Sort)

堆排序使用 最大堆(Max Heap)最小堆(Min Heap) 来实现排序。

具体可以参考这篇文章:理解堆的哇塞大碗大碗吗。 , ,/,/ 发 的特性与应用

1.2 快速选择(QuickSelect)算法解决 Top K 问题

如果你使用 选择排序 来解决 Top K(Tok)问题,实际上不需要对整个数组进行完整排序,而是只运行 K 次选择过程 来找到 第 K 大(或 K 小)元素

具体可以参考这篇文章:七大常见排序

3.在Tok问题,什么时候使用大根堆和小根堆?

大根堆(Max Heap):用于获取最大元素或 Top K 最小元素(维持 K 个最小元素,堆顶最大)。示例:找 前 K 小(维护大小为 K 的大根堆)。小根堆(Min Heap):用于获取最小元素或 Top K 最大元素(维持 K 个最大元素,堆顶最小)。示例:找 前 K 大(维护大小为 K 的小根堆)。

1046. 最后一块石头的重量

题目】:1046. 最后一块石头的重量

在这里插入图片描述

算法思路

在这里插入图片描述

利用堆的特性,反复取出当前最大值和次大值进行碰撞处理,然后将结果重新插入堆中。

代码实现

classSolution{public:intlastStoneWeight(vector<int>& stones){int n = stones.size(); priority_queue<int> head;for(auto x: stones) head.push(x);while(head.size()>1){int x = head.top(); head.pop();int y = head.top(); head.pop();if(x > y) head.push(x - y);}return head.size()? head.top():0;}};

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

题目】:703. 数据流中的第 K 大元素

在这里插入图片描述

算法思路

该题主要考察 Top K 问题的处理方法。为了查找第 K 大元素,我们使用小根堆。当插入新元素时,如果堆的大小超过 K,就会移除堆顶元素(即最小值)。

每次插入时,堆会自动调整,保持堆顶为当前 K 个最大元素中的最小值。如果插入的元素大于堆顶,则替换堆顶元素;如果小于堆顶,则保持堆不变。通过这种方式,堆会动态维护第 K 大元素。

代码实现

classKthLargest{public: priority_queue<int, vector<int>, greater<int>> heap;int _k;KthLargest(int k, vector<int>& nums){ _k = k;for(auto x : nums){ heap.push(x);if(heap.size()> _k) heap.pop();}}intadd(int val){ heap.push(val);if(heap.size()> _k) heap.pop();return heap.top();}};

692. 前K个高频单词

题目】:692. 前K个高频单词

在这里插入图片描述

算法思路

在这里插入图片描述

本题明确要求使用堆来解决 Top K 问题,接下来我们分析其算法思路

要使用堆来解决 Top K 问题,需要根据题目要求选择合适的堆结构。这里有两种排序策略:
频次:小根堆

  • 按频次排序:使用小根堆,确保堆顶始终是当前 K 个元素中频次最低的。
  • 按字典序排序(当频次相同时):使用大根堆,保证相同频次下按字典序降序排列。

由于字典序排序是频次排序的子集,我们可以在比较函数中添加 if 语句,灵活实现多条件排序。最终结果需要倒序遍历,因为答案要求按照单词出现频率从高到低排序,因此我们使用小根堆来维护前 K 个高频元素。

代码实现

classSolution{public:typedef pair<string,int> PSI;structCmp{booloperator()(const PSI & a,const PSI & b){if(a.second == b.second){return a.first < b.first;}return a.second > b.second;}}; vector<string>topKFrequent(vector<string>& words,int k){//1.统计单词出现次数 unordered_map<string,int> hash;for(auto& str : words) hash[str]++;//2.创建一个大小为 k 的堆(存储频率) priority_queue<PSI, vector<PSI>, Cmp> heap;//3.Tok逻辑for(auto& psi : hash){ heap.push(psi);if(heap.size()> k) heap.pop();}//4.提取结果 vector<string>ret(k);for(int i = k -1; i >=0; i--){ ret[i]= heap.top().first; heap.pop();}return ret;}};

295. 数据流的中位数

题目】:295. 数据流的中位数

在这里插入图片描述

算法思路

在这里插入图片描述

由于数据量庞大,前两种解法可能会超时。接下来介绍一种优化解法,虽然不太容易直接想到,但学会后会觉得非常简单。这个方法与栈用于括号匹配或出栈队列类似,思路是用大小堆来维护数据流的中位数。遇到类似问题时,可以考虑使用这种思路。

解法三:大小堆来维护数据流的中位数

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

根据准则 m == nm > n (m == n + 1),我们根据 num 的值进行分类讨论。当 num < x 时,放入大根堆,否则放入小根堆。然后根据这两个准则和两个堆的数量关系,进行适当的调整和维护。

在这里插入图片描述

代码实现

classMedianFinder{public: priority_queue<int> left;//大根堆 priority_queue<int,vector<int>, greater<int>> right;//小根堆MedianFinder(){}voidaddNum(int num){if(left.size()== right.size()){if(left.size()==0|| num <= left.top()) left.push(num);elseif(num > left.top()){ right.push(num); left.push(right.top()); right.pop();}}else{if(num <= left.top()){ left.push(num); right.push(left.top()); left.pop();}elseif(num > left.top()) right.push(num);}}doublefindMedian(){if(left.size()== right.size())return((left.top()+ right.top())/2.0);elsereturn left.top();}};

细节问题

为了避免在访问 left.top() 时出现非法访问,我们应该首先检查 left 大根堆是否为空。具体来说,条件 left.size() == 0 || num <= left.top() 确保只有在堆非空且 num 小于等于堆顶元素时,才执行相关操作。

在这里插入图片描述


快和小二一起踏上精彩的算法之旅!关注我,我们将一起破解算法奥秘,探索更多实用且有趣的知识,开启属于你的编程冒险!

Read more

【Java Web学习 | 第五篇】CSS(4) -盒子模型

【Java Web学习 | 第五篇】CSS(4) -盒子模型

🌈个人主页: Hygge_Code🔥热门专栏:从0开始学习Java | Linux学习| 计算机网络💫个人格言: “既然选择了远方,便不顾风雨兼程” 文章目录 * CSS盒子模型🥝 * 1. 什么是CSS盒子模型? * 2. 边框(border):盒子的"外衣"🍋‍🟩 * 边框的基本属性 * 单边边框设置 * 边框对盒子大小的影响 * 表格细线边框 * 3. 内边距(padding):内容与边框的缓冲带🍋‍🟩 * 内边距的基本用法 * 内边距对盒子大小的影响 * 内边距的实用技巧 * 内边距不影响盒子大小的特殊情况 * 4. 外边距(margin):盒子之间的距离🍋‍🟩 * 外边距的基本用法 * 外边距的典型应用:水平居中 * 外边距合并问题 * 清除默认内外边距🐦‍🔥 * 综合代码演示 * CSS美化三剑客:圆角边框、盒子阴影与文字阴影🥝 * 1. 圆角边框(border-radius):告别生

By Ne0inhk

微信小程序如何优雅地跳转外部链接?WebView + 复制方案实战

在做小程序开发的过程中,我们经常会遇到这样一个需求: 👉 用户在小程序里点开一个课程/资料,需要跳转到公司内部的学习系统或者外部网站。 问题来了: * 小程序禁止直接用 <a> 标签跳转外部网页 * 也不能像浏览器里那样用 window.open * 那么,怎么实现呢? 这篇文章我会结合实际项目,聊聊 两种常见方案: 1. 业务域名 + WebView 打开外部链接 2. 不在业务域名里的 → 自动复制链接 1️⃣ 背景:小程序的安全限制 微信对小程序的外部链接有严格限制: * 只能通过 <WebView /> 组件来加载 H5 页面。 * 这个 H5 的域名,必须提前在 小程序后台 → 开发设置 → 业务域名 配置。 * 没配置的域名,一律打不开。 所以,解决问题的第一步就是搞清楚: 👉 目标链接的域名是否可控、

By Ne0inhk
湖南首条免费高速轨迹呈现:借助 Leaflet -Trackplayer 实现 WebGIS 可视化

湖南首条免费高速轨迹呈现:借助 Leaflet -Trackplayer 实现 WebGIS 可视化

目录 前言 一、相关背景 1、湖南首条免费高速-长永高速 2、还有哪些快到30年的高速 3、leaflet-trackplayer相关知识 二、基础数据准备 1、高速起止点地理编码 2、途径重要AOI和POI信息 3、高速区间道路信息 三、leaflet-trackplayer实战 1、行驶道路生成和设置 2、途径重要AOI和POI 3、车辆车牌信息模拟跟随 4、成果展示 四、总结 前言         在交通基础设施建设与数字化技术飞速发展的时代,湖南迎来了其首条免费高速公路的建成通车,这不仅是交通领域的一大突破,更是区域经济发展与民生改善的重要里程碑。然而,如何更好地展示这条高速公路的运行轨迹,为交通管理、规划以及公众出行提供直观,成为了我们亟待解决的问题。将WebGIS 技术与 Leaflet - Trackplayer 的结合,为我们提供了一种创新且高效的解决方案。WebGIS(Web 地理信息系统)

By Ne0inhk

WebP格式简记

文章目录 * 概述 * 开发背景 * 核心技术原理 * 有损压缩 * 无损压缩 * 动画与扩展功能 * 核心技术特性 * 兼容性现状与性能 * 全平台生态支持 * 编解码性能表现 * 实际应用与生态 * 核心应用要点 * 工具与生态支持 * 优缺点与发展趋势 * 核心优缺点 * 发展趋势 概述 WebP(Web Picture)是由Google开发的开源光栅图像格式,自2010年推出以来,凭借高压缩效率与全功能支持的技术特性,逐步成为替代JPEG、PNG、GIF的现代Web图像标准,更是网页性能优化、移动端资源轻量化的核心选择。 该格式基于视频编码技术创新,完美解决了传统图像格式在压缩率、功能兼容性上的痛点,目前已被纳入W3C标准,成为跨端图像传输的主流方案,其核心目标是提升网页加载速度、降低带宽消耗,特别适用于Web和移动应用场景。 对于绝大多数Web应用而言,将JPEG/PNG/GIF迁移至WebP可带来显著的性能收益,且实施成本低、风险可控,WebP已从“可选优化”转变为现代Web开发的标准实践。

By Ne0inhk