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

Java--利用(堆)获取前k个最小元素

目录

一、问题背景

二、核心方法解析

关键点说明:

三、优化思路(进阶)

四、完整代码实现

五、方法对比

六、面试题

七、总结


正文开始

一、问题背景

在处理数据时,我们经常需要快速获取一个数组中前k个最小的元素。例如:

  • 在推荐系统中筛选评分最低的商品
  • 在数据分析中提取温度最低的k个城市

本文将介绍如何通过Java的PriorityQueue高效实现这一功能。

二、核心方法解析

// 方法签名
public int[] smallestK(int[] arr, int k) {PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();for (int num : arr) {priorityQueue.offer(num); // 所有元素入队(默认小根堆)}int[] ret = new int[k];for (int i = 0; i < k; i++) {ret[i] = priorityQueue.poll(); // 依次取出堆顶元素(即最小值)}return ret;
}

关键点说明:

  • 优先级队列特性Java的PriorityQueue默认是小根堆,堆顶始终为最小元素
  • 时间复杂度:O(n log n) + O(k log n) → 总体为O(n log n)
  • 空间复杂度:O(n)(需存储所有元素)

三、优化思路(进阶)

当数据量极大时,可采用大根堆优化,将时间复杂度降低至O(n log k)

// 使用大根堆(仅保留k个最小元素)
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);
for (int num : arr) {if (maxHeap.size() < k) {maxHeap.offer(num);} else if (num < maxHeap.peek()) {maxHeap.poll();maxHeap.offer(num);}
}

四、完整代码实现

import java.util.PriorityQueue;public class TopKSmallest {// 方法1:直接使用小根堆public int[] smallestK(int[] arr, int k) {if (k <= 0) return new int[0];PriorityQueue<Integer> pq = new PriorityQueue<>();for (int num : arr) {pq.offer(num);}int[] result = new int[k];for (int i = 0; i < k; i++) {result[i] = pq.poll();}return result;}// 方法2:大根堆优化版(推荐)public int[] smallestKOptimized(int[] arr, int k) {if (k <= 0) return new int[0];PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);for (int num : arr) {if (maxHeap.size() < k) {maxHeap.offer(num);} else if (num < maxHeap.peek()) {maxHeap.poll();maxHeap.offer(num);}}return maxHeap.stream().mapToInt(i -> i).toArray();}public static void main(String[] args) {int[] data = {12, 3, 5, 7, 19, 2, 16};TopKSmallest solver = new TopKSmallest();System.out.println(Arrays.toString(solver.smallestK(data, 3)));    // [2, 3, 5]System.out.println(Arrays.toString(solver.smallestKOptimized(data, 3))); // [5, 3, 2]}
}

五、方法对比

方法时间复杂度空间复杂度适用场景
小根堆O(n log n)O(n)数据量较小
大根堆优化O(n log k)O(k)海量数据

六、面试题

面试题 17.14. 最小K个数 - 力扣(LeetCode)

七、总结

  • 小根堆方法:实现简单,但空间占用高,适合小数据集
  • 大根堆优化:通过动态维护k个元素,显著降低时间和空间复杂度
  • 实际开发中应根据数据规模选择合适方案

http://www.xdnf.cn/news/503191.html

相关文章:

  • 非易失性存储技术综合对比:EEPROM、NVRAM、NOR Flash、NAND Flash和SD卡
  • ​哈夫曼树(Huffman Tree)
  • C++ 回调函数
  • 计算机视觉与深度学习 | Python实现EEMD-LSTM时间序列预测(完整源码和数据)
  • JavaScript基础-预解析
  • 线程(二)OpenJDK 17 中线程启动的完整流程用C++ 源码详解之主-子线程通信机制
  • 如何彻底清空docker里面不使用的容器?
  • deepin v23.1 搜狗输入法next配置中文输入法下默认用英文标点
  • 符合Python风格的对象(对象表示形式)
  • 【机器学习】第二章模型的评估与选择
  • 【LeetCode】大厂面试算法真题回忆(91)--几何平均值最大子数组
  • vue引用cesium,解决“Not allowed to load local resource”报错
  • 调用DeepSeek系列模型问答时,输出只有</think>标签,而没有<think>标签
  • 无人机视角垃圾检测数据集VOC+YOLO格式771张1类别
  • 使用Maven和Ant上传文件到Linux服务器
  • 交流学习 | 江西同为科技有限公司赴海尔总部考察交流
  • Vue3学习(组合式API——父、子组件间通信详解)
  • 大模型之RAG知识库
  • 实验三:计划任务和时钟同步
  • 经典算法 求C(N, K) % mod,保证mod是质数
  • 打造文本差异对比工具 TextDiffX:从想法到实现的完整过程
  • 嵌入式软件的分层架构
  • GitHub 趋势日报 (2025年05月16日)
  • H3C UIS 超融合管理平台原理解读以及日常运维实操与故障处理
  • Transformer 架构在目标检测中的应用:YOLO 系列模型解析
  • 便捷的批量打印工具推荐
  • PyQt5基本窗口控件(QSlider(滑动条))
  • 【计网】 ARP地址解析协议 [工作过程]
  • hyper-v 虚拟机怎么克隆一台一样的虚拟机?
  • NHANES指标推荐:FMI