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

二刷 LeetCode:215. 数组中的第 K 个最大元素 347. 前 K 个高频元素 复盘笔记

目录

一、215. 数组中的第 K 个最大元素

题目回顾

思路复盘

方法 1:小顶堆(优先队列)

方法 2:快速选择(优化版快排)

易错点 & 二刷心得

二、347. 前 K 个高频元素

题目回顾

思路复盘

方法 1:哈希表 + 小顶堆

方法 2:桶排序

易错点 & 二刷心得

三、两道题的共性总结 & 二刷收获


这两道题是堆 / 优先队列的经典考点,也是面试中高频的 Top K 问题,二刷时我们重点拆解思路、对比不同解法,顺便把易错点和通用模板总结清楚。


一、215. 数组中的第 K 个最大元素

题目回顾

给定整数数组nums和整数k,请返回数组中第k个最大的元素。请注意,你需要找的是数组排序后的第k个最大的元素,而不是第k个不同的元素。

思路复盘

这道题有两种主流解法:堆(优先队列)快速选择,其中堆是面试中最常考的解法。

方法 1:小顶堆(优先队列)

核心思路:维护一个大小为k的小顶堆,遍历数组时:

  • 如果堆的大小小于k,直接将元素加入堆中
  • 如果堆的大小等于k,比较当前元素和堆顶元素:
    • 若当前元素大于堆顶元素,则弹出堆顶,加入当前元素
    • 否则跳过
  • 遍历结束后,堆顶元素就是第k个最大的元素

Java 代码实现

java

运行

public int findKthLargest(int[] nums, int k) { PriorityQueue<Integer> minHeap = new PriorityQueue<>(); for (int num : nums) { if (minHeap.size() < k) { minHeap.offer(num); } else { if (num > minHeap.peek()) { minHeap.poll(); minHeap.offer(num); } } } return minHeap.peek(); }
方法 2:快速选择(优化版快排)

核心思路:利用快排的分区思想,每次将数组分为两部分,根据基准元素的位置,缩小查找范围:

  • 如果基准元素的位置等于n-k,则基准元素就是答案
  • 如果基准元素的位置大于n-k,则在左半部分继续查找
  • 如果基准元素的位置小于n-k,则在右半部分继续查找

Java 代码实现

java

运行

public int findKthLargest(int[] nums, int k) { return quickSelect(nums, 0, nums.length - 1, nums.length - k); } private int quickSelect(int[] nums, int left, int right, int targetIndex) { int pivotIndex = partition(nums, left, right); if (pivotIndex == targetIndex) { return nums[pivotIndex]; } else if (pivotIndex < targetIndex) { return quickSelect(nums, pivotIndex + 1, right, targetIndex); } else { return quickSelect(nums, left, pivotIndex - 1, targetIndex); } } private int partition(int[] nums, int left, int right) { int pivot = nums[right]; int i = left; for (int j = left; j < right; j++) { if (nums[j] <= pivot) { swap(nums, i, j); i++; } } swap(nums, i, right); return i; } private void swap(int[] nums, int i, int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; }

易错点 & 二刷心得

  1. 堆的选择:找第k个最大元素用小顶堆,找第k个最小元素用大顶堆,不要搞混。
  2. 时间复杂度:小顶堆的时间复杂度是 O (nlogk),快速选择的平均时间复杂度是 O (n),最坏情况是 O (n²),实际面试中优先推荐堆的解法。
  3. 边界处理:快速选择时,目标索引是n-k,而不是k-1,注意区分从大到小和从小到大的排序。

二、347. 前 K 个高频元素

题目回顾

给你一个整数数组nums和一个整数k,请你返回其中出现频率前k高的元素。你可以按任意顺序返回答案。

思路复盘

这道题是哈希表 + 堆的经典组合,也可以用桶排序的方法解决。

方法 1:哈希表 + 小顶堆

核心思路:

  1. 先用哈希表统计每个元素的出现频率
  2. 维护一个大小为k的小顶堆,堆中元素按频率排序
  3. 遍历哈希表,将元素加入堆中,最终堆中的元素就是前k个高频元素

Java 代码实现

java

运行

public int[] topKFrequent(int[] nums, int k) { // 1. 统计频率 Map<Integer, Integer> freqMap = new HashMap<>(); for (int num : nums) { freqMap.put(num, freqMap.getOrDefault(num, 0) + 1); } // 2. 小顶堆,按频率排序 PriorityQueue<Map.Entry<Integer, Integer>> minHeap = new PriorityQueue<>((a, b) -> a.getValue() - b.getValue()); for (Map.Entry<Integer, Integer> entry : freqMap.entrySet()) { if (minHeap.size() < k) { minHeap.offer(entry); } else { if (entry.getValue() > minHeap.peek().getValue()) { minHeap.poll(); minHeap.offer(entry); } } } // 3. 取出结果 int[] result = new int[k]; int index = 0; while (!minHeap.isEmpty()) { result[index++] = minHeap.poll().getKey(); } return result; }
方法 2:桶排序

核心思路:

  1. 先用哈希表统计每个元素的出现频率
  2. 创建一个桶数组,桶的索引表示频率,桶中存放对应频率的元素
  3. 从后往前遍历桶数组,收集前k个元素

Java 代码实现

java

运行

public int[] topKFrequent(int[] nums, int k) { // 1. 统计频率 Map<Integer, Integer> freqMap = new HashMap<>(); for (int num : nums) { freqMap.put(num, freqMap.getOrDefault(num, 0) + 1); } // 2. 创建桶 List<List<Integer>> buckets = new ArrayList<>(); for (int i = 0; i <= nums.length; i++) { buckets.add(new ArrayList<>()); } for (Map.Entry<Integer, Integer> entry : freqMap.entrySet()) { buckets.get(entry.getValue()).add(entry.getKey()); } // 3. 从后往前收集结果 int[] result = new int[k]; int index = 0; for (int i = buckets.size() - 1; i >= 0 && index < k; i--) { List<Integer> bucket = buckets.get(i); for (int num : bucket) { result[index++] = num; if (index == k) { break; } } } return result; }

易错点 & 二刷心得

  1. 堆的比较器:在 Java 中,PriorityQueue默认是小顶堆,所以自定义比较器时要按频率升序排列。
  2. 桶排序的适用场景:当元素频率分布较广时,桶排序的空间复杂度较高,但时间复杂度是 O (n),效率更高。
  3. 结果顺序:题目不要求返回元素的顺序,所以两种方法的结果都可以直接返回,不需要额外排序。

三、两道题的共性总结 & 二刷收获

  1. Top K 问题的通用解法
    • 小顶堆:时间复杂度 O (nlogk),空间复杂度 O (k),适用于大部分场景
    • 快速选择:平均时间复杂度 O (n),空间复杂度 O (1),适用于数组可修改的场景
    • 桶排序:时间复杂度 O (n),空间复杂度 O (n),适用于频率分布较集中的场景
  2. 堆的核心思想:维护一个大小为k的堆,用堆顶元素过滤掉不需要的元素,最终堆中保留的就是前k个元素。
  3. 面试重点
    • 第 K 个最大元素:堆的实现和快速选择的优化思路,以及时间复杂度分析
    • 前 K 个高频元素:哈希表和堆的结合,桶排序的实现和适用场景
http://www.jsqmd.com/news/738821/

相关文章:

  • 嵌入式固件防篡改测试失效真相(92%工程师忽略的CRC32校验盲区与SHA-256硬件加速陷阱)
  • 2026年Turnitin AI检测升级深度解读:新版本对留学生论文降AI影响完整分析 - 还在做实验的师兄
  • H5Maker开源编辑器:3步搭建你的专属H5创作平台
  • HuixiangDou:专为群聊场景设计的智能知识助手部署与实战
  • 网络卡顿排查不求人:5分钟用iperf3定位是带宽瓶颈还是延迟问题(Windows/Mac/Linux全平台指南)
  • SABnzbd(二进制新闻阅读器) 5.0
  • 2026年体育学论文降AI工具推荐:运动科学研究4.8元极速降AI完整指南 - 还在做实验的师兄
  • AI智能体安全审计:基于密码学账本与策略引擎的EctoClaw实践
  • 解锁Mac游戏控制新境界:360Controller让你的Xbox手柄重获新生
  • 观察 Taotoken 在不同网络环境下 API 调用的延迟表现与容灾感受
  • 【工业级C语言OTA配置标准V2.3】:基于STM32+FreeRTOS的12项强制校验清单(附可审计配置表)
  • 抖音下载器终极指南:三步实现批量无水印下载,效率提升90%
  • 面试必问!MySQL 事务到底是怎么实现的?这篇文章讲透了
  • 为什么你的YOLOv5在树莓派跑不动?Python轻量化不是“简单剪枝”——资深边缘架构师拆解4层冗余消除机制(含热力图可视化诊断)
  • 如何高效解放双手:绝区零一条龙智能自动化助手实战指南
  • 2026年公共管理论文降AI工具推荐:行政管理政策研究答辩前知网达标方案 - 还在做实验的师兄
  • C语言OTA固件差分升级调试实录(基于bsdiff+ed25519签名验证的端到端调试日志还原)
  • 别再死记硬背Nash均衡了!用Python模拟‘囚徒困境’和‘性别战’,5分钟搞懂博弈论核心
  • 学术研究中事实陈述提取的技术实现与应用
  • 【Python低代码平台插件化开发实战指南】:20年架构师亲授5大核心设计模式与3个工业级落地案例
  • AKShare金融数据接口库:Python量化分析的完整高效解决方案
  • 刷蛋机哪家好:企业选购核心标准标准与策略深度解析
  • 告别Outlook!Foxmail 7.2.25保姆级配置教程,手把手教你同步Gmail和企业微信
  • 解锁Switch游戏新境界:3步掌握大气层整合包安装与优化
  • 智能作业车辆路径规划【附ROS仿真】
  • 如何在普通PC上安装macOS:OpenCore完整配置方案指南
  • 2026年农业科学论文降AI工具推荐:农学园艺畜牧研究亲测99.26%达标指南 - 还在做实验的师兄
  • 从传感器数据到颜色判断:用FPGA处理ZC-CLS381RGB的RGB原始值(含阈值设定技巧)
  • 在Node.js后端服务中集成Taotoken实现稳定的大模型能力调用
  • WaveTools鸣潮工具箱:终极免费工具箱解锁游戏新体验 [特殊字符]