news 2026/5/3 21:06:07

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
二刷 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 个高频元素:哈希表和堆的结合,桶排序的实现和适用场景
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/3 20:19:24

2026届学术党必备的六大AI论文方案实测分析

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 人工智能技术给毕业论文写作供给、提供了全新的辅助路径做法、方式。当下、当前&#xff0c;…

作者头像 李华
网站建设 2026/5/4 5:28:15

Android设备管理终极指南:Escrcpy如何彻底改变你的工作流

Android设备管理终极指南&#xff1a;Escrcpy如何彻底改变你的工作流 【免费下载链接】escrcpy &#x1f4f1; Display and control your Android device graphically with scrcpy. 项目地址: https://gitcode.com/GitHub_Trending/es/escrcpy 在移动开发、测试和设备管…

作者头像 李华
网站建设 2026/5/4 5:28:19

告别S32DS!手把手教你用MDK-Keil搭建S32K144开发环境(附完整工程模板)

从S32DS迁移到MDK-Keil&#xff1a;打造高效S32K144开发工作流 如果你已经习惯了MDK-Keil的开发环境&#xff0c;却因为项目需要转向NXP的S32K144系列MCU开发&#xff0c;这篇文章将为你提供一个无缝过渡的完整方案。我们将深入探讨为什么Keil可能是比官方推荐的S32DS更适合你的…

作者头像 李华
网站建设 2026/5/2 15:08:31

郑斯仁棒球写真曝光,挥棒蓄力少年如斯

近日&#xff0c;一组以棒球为灵感的运动写真曝光了郑斯仁最松弛的模样。镜头下的郑斯仁&#xff0c;时而戴着黑色头盔凝视远方&#xff0c;眼神里藏着锐气与沉思&#xff1b;时而手握球棒&#xff0c;在蓝天绿草间摆出击球姿势&#xff0c;白色运动装衬得他身姿挺拔&#xff0…

作者头像 李华
网站建设 2026/5/3 23:13:47

为Claude Code编程助手配置Taotoken作为稳定可靠的后端模型服务

为Claude Code编程助手配置Taotoken作为稳定可靠的后端模型服务 1. 为什么选择Taotoken作为Claude Code的后端服务 对于使用Claude Code这类编程辅助工具的开发者而言&#xff0c;稳定可靠的模型服务是保证开发效率的关键。Taotoken平台通过聚合分发多厂商的大模型能力&#…

作者头像 李华