从M个元素中查找最小的N个元素时,使用大顶堆的效率比使用小顶堆更高,为什么?

我们有一个长度为 M 的数组,现在我们想从中找出 最小的 N 个元素。例如:

cpp 复制代码
int a[10] = {12, 3, 5, 7, 19, 0, 8, 2, 4, 10};

从中找出 最小的 4 个元素


正确方法:使用大小为 N 的「大顶堆」

原因分析:

我们想保留最小的 4 个元素,因此可以使用一个大顶堆,堆的作用是"维护最小的 N 个数"。

思路如下:

  1. 初始化:先把前 4 个数放入堆中 → 12, 3, 5, 7
    • 堆顶为最大值 12,表示目前"最小的 4 个元素"中最大的那个是 12。
  2. 从第 5 个数开始往后遍历数组,只要当前数 < 堆顶,就替换堆顶
  3. 最终堆中留下的是"最小的 4 个数"。

具体步骤(维护一个大顶堆):

初始数组:

cpp 复制代码
{12, 3, 5, 7, 19, 0, 8, 2, 4, 10}

步骤:

  • 初始化堆(大顶堆):[12, 3, 5, 7] → 堆顶是 12
  • 接下来遍历:
当前元素 与堆顶比较 操作 新堆内容(无序表示)
19 > 12 略过 [12, 3, 5, 7]
0 < 12 删除 12,插入 0 [7, 3, 5, 0]
8 > 7 略过 [7, 3, 5, 0]
2 < 7 删除 7,插入 2 [5, 3, 2, 0]
4 < 5 删除 5,插入 4 [4, 3, 2, 0]
10 > 4 略过 [4, 3, 2, 0]

最终堆中元素:[0, 2, 3, 4]


如果用小顶堆会怎么样?

假如你误用了小顶堆,初始堆是 [3, 12, 5, 7],堆顶是 3。

你遍历后面的元素时,堆顶一直是最小的那个,永远不会被替换掉。

问题是:你不知道当前 4 个是不是最小的 4 个,因为最大值还留在里面!

你得存下所有 M 个元素,再从小顶堆中取前 N 个,等于多维护了不必要的 M - N 个元素,效率大大降低。


总结口诀:

🔹 找最小的 N 个数 → 用大小为 N 的大顶堆 ,因为你要踢走大的。

🔹 找最大的 N 个数 → 用大小为 N 的小顶堆,因为你要踢走小的。


相关推荐
QiLinkOS5 小时前
第三视觉理解徐玉生与他的商业活动(30)
大数据·c++·人工智能·算法·开源协议
疯狂打码的少年5 小时前
【操作系统】页面置换算法(OPT/FIFO/LRU)
算法
小O的算法实验室6 小时前
2026年CIE,优化客货协同运输:综合地铁系统的列车容量动态分配
算法
Coder_Shenshen6 小时前
西门子S7CommPlus协议鉴权算法原理与流程详解
网络·后端·算法
硕风和炜7 小时前
【LeetCode: 2492. 两个城市间路径的最小分数 + DFS】
java·算法·leetcode·深度优先·dfs·bfs·并查集
我是一颗柠檬8 小时前
【Java项目技术亮点】加权轮询负载均衡算法
java·算法·负载均衡
灯厂码农8 小时前
C语言动态内存分配完全指南(malloc、calloc、realloc、free)
java·c语言·算法
凯瑟琳.奥古斯特9 小时前
K次取反最大化数组和解法(力扣1005)
开发语言·c++·算法·leetcode·职场和发展
Jerry10 小时前
LeetCode 203. 移除链表元素
算法
地平线开发者10 小时前
征程 6 | 工具链 QAT ObserverBase 源码解析
算法