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

巧用小顶堆求解第 K 大元素,两道经典题一通百通

巧用小顶堆求解第 K 大元素,两道经典题一通百通✨

  • Bilibili 同步视频
  • 一、前言💡
  • 二、核心思路剖析📜
    • 2.1 逻辑推演
    • 2.2 文字图示演示(Plain Text)
      • 初始状态:空堆,设定 K = 3
      • 步骤 1:依次压入前 3 个元素 [9, 7, 8],堆满(size = 3)
      • 步骤 2:新增元素 10,入堆后堆 size = 4 > K=3
      • 步骤 3:新增元素 6,入堆后堆 size = 4 > K=3
  • 三、复杂度分析⚙️
  • 四、C++ 代码实现💻
    • 4.1 解法一:数组中的第 K 大元素
    • 4.2 解法二:数据流中的第 K 大元素
    • 代码解读📝
  • 五、总结与刷题建议📝

🔖 标签:# 算法 #堆结构 #C++ #面试题 #数据结构


Bilibili 同步视频

巧用小顶堆求解第 K 大元素,两道经典题一通百通✨


一、前言💡

在算法刷题与面试场景中,求解数组 / 数据流中的第 K 大元素,是一道出镜率极高的经典题型。不少初学者面对该问题时,常会陷入全量排序、暴力遍历的低效思路中。实则借助小顶堆这一精巧的数据结构,便可化繁为简、四两拨千斤。本文将由浅入深拆解解题逻辑、推演执行流程、附上完整 C++ 代码,并辅以图文演示原理,带你彻底吃透这两道同源考题。


二、核心思路剖析📜

世间算法,万变不离其宗。两道看似独立的题目 ——数据流中的第 K 大元素数组中的第 K 大元素,内核逻辑高度趋同,皆可依托小顶堆实现高效求解。

2.1 逻辑推演

设我们需要筛选出一组数据里排名前K KK的大数:

  1. 若某元素想要跻身前 K 大序列,其数值必须大于当前前 K 个元素里的最小值

  2. 一旦新元素达标,便淘汰原有 K 个元素中的最小值,完成一轮更新迭代;

  3. 为了实时、快速获取当前 K 个元素的最小值,小顶堆便是最优选择。

小顶堆特性:堆顶永远是整个堆结构中的最小值,查询、弹出堆顶元素的时间复杂度极低。

📌 总结要义:
容量为 K 的小顶堆维护全局前 K 大元素,堆内留存当前筛选出的 K 个大数,堆顶即为整组数据的第 K 大元素。谁数值更小,便被优先移出堆外,恰似择优留强、汰弱留庸。

2.2 文字图示演示(Plain Text)

初始状态:空堆,设定 K = 3

堆结构:[ 空 ] 目标:筛选前3大元素,最终堆顶为第3大元素

步骤 1:依次压入前 3 个元素 [9, 7, 8],堆满(size = 3)

小顶堆自动调整结构,堆顶为最小值7

7 ← 堆顶(当前前3大最小值) / 9 8 堆内元素:{7,9,8}

步骤 2:新增元素 10,入堆后堆 size = 4 > K=3

堆顶最小值7被弹出,重新调整堆结构,新堆顶为8

8 ← 新堆顶 / 9 10 堆内元素:{8,9,10}

步骤 3:新增元素 6,入堆后堆 size = 4 > K=3

堆顶最小值6被弹出,堆结构不变

8 ← 堆顶(最终第3大元素) / 9 10

全程可见:无论元素如何新增更替,堆内始终保留当前前 K 大元素,堆顶就是我们所求的第 K 大元素。


三、复杂度分析⚙️

设数据总个数为n nn,限定堆容量为K KK

  1. 时间复杂度:每个元素入堆、堆调整操作耗时O ( l o g K ) O(log K)O(logK),整体总复杂度为O ( n l o g K ) O(nlog K)O(nlogK)
    对比全量排序O ( n l o g n ) O(nlog n)O(nlogn),当K l l n K ll nKlln时,效率提升十分显著。

  2. 空间复杂度:仅开辟大小为K KK的堆空间,复杂度为O ( K ) O(K)O(K),内存占用极小。


四、C++ 代码实现💻

C++ 标准库中,默认优先队列priority_queue大顶堆,我们可通过仿函数greater<int>改造为小顶堆,适配本题需求。

4.1 解法一:数组中的第 K 大元素

适用于一次性给定完整数组,直接求解第 K 大元素场景。

#include<iostream>#include<vector>#include<queue>// 优先队列(堆)头文件usingnamespacestd;// 查找数组中第 K 大元素intfindKthLargest(vector<int>&nums,intk){// 定义小顶堆:priority_queue<数据类型, 底层容器, 比较规则>priority_queue<int,vector<int>,greater<int>>minHeap;// 遍历所有元素,逐个入堆for(intnum:nums){minHeap.push(num);// 堆容量超过 K,弹出堆顶最小值if(minHeap.size()>k){minHeap.pop();}}// 最终堆顶即为第 K 大元素returnminHeap.top();}intmain(){vector<int>arr={3,2,1,5,6,4};intk=2;intres=findKthLargest(arr,k);cout<<"数组中第"<<k<<"大元素为:"<<res<<endl;return0;}

4.2 解法二:数据流中的第 K 大元素

适用于动态持续流入数据的场景,支持不断添加新数值,实时查询第 K 大元素。

#include<iostream>#include<vector>#include<queue>usingnamespacestd;classKthLargest{private:intk;// 小顶堆,维护前 K 大元素priority_queue<int,vector<int>,greater<int>>minHeap;public:// 构造函数:初始化 K 值与初始数据流KthLargest(intk_val,vector<int>&nums){k=k_val;for(intnum:nums){minHeap.push(num);if(minHeap.size()>k){minHeap.pop();}}}// 新增数据流元素,并返回当前第 K 大元素intadd(intval){minHeap.push(val);if(minHeap.size()>k){minHeap.pop();}returnminHeap.top();}};intmain(){vector<int>stream={4,5,8,2};intk=3;KthLargestkthLargest(k,stream);// 动态添加元素并输出结果cout<<kthLargest.add(3)<<endl;cout<<kthLargest.add(5)<<endl;cout<<kthLargest.add(10)<<endl;return0;}

代码解读📝

  1. priority_queue<int, vector<int>, greater<int>>:第三参数greater<int>是构建小顶堆的核心,堆顶始终为最小值;

  2. 元素入堆后强制校验堆大小,一旦超出K KK,立即弹出堆顶最小值,保证堆内永远只留存前 K 大元素;

  3. 数据流版本将逻辑封装为类,构造函数初始化初始数据,add方法响应动态新增数据,贴合真实业务场景。


五、总结与刷题建议📝

纵观两道同源题型,小顶堆 + 固定容量 K是贯穿始终的核心解法,思路一脉相承:
以小顶堆作 “筛选容器”,守 K 位、汰小值,堆顶定论答案。此思路摒弃了全量排序的冗余操作,时空表现俱佳,也是面试中面试官尤为青睐的解法。

✅ 刷题建议:

  1. 先理解堆的底层特性,分清大顶堆、小顶堆的使用场景;

  2. 亲手调试上述两份代码,观察堆内元素变化,对照前文图示加深理解;

  3. 前往力扣平台找到对应原题独立编写代码,巩固思路,做到提笔即写、思路通透。

算法学习非一日之功,吃透一类题型、掌握一种思想,便可举一反三,从容应对同类变式考题。

http://www.jsqmd.com/news/1138409/

相关文章:

  • 3步掌握DLSS Swapper:游戏画质升级的终极神器
  • CBAM 注意力模块 PyTorch 实战:3 步集成 ResNet-50,ImageNet 精度提升 1.2%
  • UL 1069-2024新版护士呼叫设备安全标准,这些技术更新必须吃透
  • 【Bug已解决】Claude Code Bedrock 报错 cache_control scope 字段不支持解决方案
  • 【Bug已解决】Claude Code 报错 Claude‘s response exceeded the 32000 output token limit 解决方案
  • 抖音无水印下载神器:一键批量保存视频、图集和直播内容
  • Agent 上生产的最后一公里:权限、发布、回滚和版本治理
  • 从CrackMe入门逆向工程:figugegl系列算法分析与注册机编写实战
  • 2026年亲测一键生成论文工具榜单(高效定稿版)
  • 记一次 PDF 转 Word 服务频繁崩溃的排查与解决:Java 堆内存并不是全部
  • PyTorch 实现 Nesterov 加速梯度:3 个关键参数调优与 SGD+Momentum 对比实验
  • API 香是香,但从Vue2迁移时你可别像我当初一样踩进这 3 个深坑里
  • 【小白笔记】VS Code安装附加选项逐行解释
  • Audacity音频编辑:从录音小白到剪辑高手的完整指南
  • Agent 工程化新底座:用 CLI 契约层打通 HTTP 接口与业务能力
  • 【单片机毕业设计】基于 STC89C52 的水质温浊监测报警系统设计, 基于 51 单片机的水质多参数检测控制器开发(018101)
  • AI智能体白盒测试实战:从单元测试到集成测试的完整方案
  • Cadence Allegro 17.4 电源完整性(PI)设计:解决3A大电流下的电源压降超标问题
  • 【Bug已解决】Codex CLI 执行简单命令报 command timed out 解决方案
  • 【Java项目技术亮点】红包算法二倍均值法
  • Web 安全实战:DVWA Low 级别手工检测 SQL 注入完整教程(原理 + 实操分步详解)
  • 深入了解事件相关电位及其成分(三)
  • BPF工具实战:中断、SMP调用与缓存性能
  • Go 并发的七种数据竞争陷阱:Uber 从 1100 个 Race 修复中总结出的经验
  • 2026年,中建南方环境技术如何?
  • AI之后,核聚变迎来第二个“加速器”?
  • 06-高级模式与实战项目——05. 容器与展示组件
  • Pandas 1.5 数据分析实战:电影评分数据集 3 大统计维度与 2 种分组聚合
  • STM32 裸机 Blink 的坑 你确定你的向量表能跑起来
  • Claude Sonnet 5发布、Claude Code隐写术争议、零英伟达万亿模型 | 06.29-07.05 AI周报