java中可用双堆模拟法实现双端堆:用最小堆、最大堆和延迟删除哈希表,支持o(1)获取min/max、插入及删除,双向范围检索即getmin()与getmax()组合。

Java 中标准库没有直接提供双端堆(Interval Heap),但可以通过数组手动实现一个简化版,支持 获取最小值和最大值、插入任意元素、删除最小/最大值,并支持 O(1) 时间的双向范围检索(即快速访问当前数据集的 min 和 max)。注意:严格意义上的 Interval Heap 是一种隐式双层结构(每节点存区间 [low, high]),但实际工程中常以“双端堆”泛指能高效维护 min/max 的结构;这里我们实现一个基于数组的 双堆模拟法(Two-Heap Approach),兼顾简洁性与实用性。
核心设计:用两个堆共享同一数据源
不直接手写 Interval Heap 的复杂节点区间逻辑(易出错且增删开销大),而是用两个优先队列(最小堆 + 最大堆)+ 延迟删除标记,共用底层数据数组,保证逻辑清晰、易于调试:
- 最小堆(
PriorityQueue<integer></integer>)负责维护当前最小值 - 最大堆(
PriorityQueue<integer></integer>配合Comparator.reverseOrder())负责维护当前最大值 - 使用哈希表(
Map<integer integer></integer>)记录每个值的「待删除次数」,避免物理移除导致 O(n) 开销 - 所有插入/删除操作都同步更新两个堆和计数器,查询 min/max 时先清理堆顶已失效元素
关键操作实现要点
以下为关键方法逻辑(省略完整类包装,聚焦核心):
-
插入(insert):同时加入 minHeap 和 maxHeap,并在
delayedmap 中对值计数 +1(初始为 0) -
获取最小值(getMin):循环检查 minHeap.peek() 是否在
delayed中且计数 >0;若是,poll 并递减计数,直到堆顶有效或为空 - 获取最大值(getMax):同理处理 maxHeap.peek()
-
删除最小值(popMin):调用 getMin 得到值后,在
delayed中对该值计数 +1(标记为待删),再从 minHeap poll 一次(确保下次 getMin 能跳过它) - 删除最大值(popMax):同理操作 maxHeap
注:真实删除延迟到 getMin/getMax 时执行,避免每次 pop 都遍历堆 —— 这是数组模拟双端堆最实用的取舍。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
用数组替代堆?可选轻量方案
若坚持纯数组(无 PriorityQueue)、且数据量小(如 ≤ 1000),可用简单策略:
- 维护一个动态数组
List<integer></integer>存所有元素 -
getMin()/getMax()直接遍历找极值(O(n),但代码零依赖) -
insert(x)直接 add 到末尾 -
popMin():遍历找最小索引,removeAt(index),返回值 - 适合教学演示或嵌入式场景,不推荐高频调用
双向范围检索的实际用法
所谓“双向范围检索”,本质是快速获取当前集合的 [min, max] 区间。利用上述任一实现,只需:
int rangeLow = heap.getMin();int rangeHigh = heap.getMax();- 即可立刻得到当前数据的有效范围,无需额外扫描
- 若需支持「查询是否所有元素都在 [L,R] 内」,只需判断
rangeLow >= L && rangeHigh
该能力天然支持滑动窗口极值、实时数据质量校验、自适应阈值告警等场景。
不复杂但容易忽略:延迟删除必须配合引用计数(而非布尔标记),因为相同数值可能多次插入;另外,若需支持重复元素,务必用 Integer 而非 int,避免自动装箱冲突。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










