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

【LeetCode Hot100 堆】第 K 大的元素、前 K 个高频元素

  • 堆(Heap)数据结构
    • 1. 什么是堆?
      • 两种常见类型
    • 2. 堆的存储方式
    • 3. Java 中的堆(PriorityQueue)
  • 第 K 大的元素
    • 题目描述
    • 示例
    • 使用堆求解第 K 大的元素
      • 1. 方法概述
      • 2. 解题思路
      • 3. 代码实现
  • 前 K 个高频元素
    • 1. 题目描述
    • 2. 解题思路
    • 3. 代码实现
      • 使用 `PriorityQueue`(Java 默认最小堆)
      • Map.Entry<K, V> 介绍
      • entrySet() 作用
      • Comparator.comparingInt(a -> a[1])

堆(Heap)数据结构

1. 什么是堆?

堆(Heap) 是一种 特殊的完全二叉树,满足以下性质:

  • 任意节点的值 都满足 堆的性质(最大堆或最小堆)。
  • 完全二叉树:除了最后一层,所有层都被填满,且最后一层的节点靠左排列。

两种常见类型

  1. 最小堆(Min Heap):父节点的值 小于等于 其子节点。
    • 堆顶元素 是最小值。
  2. 最大堆(Max Heap):父节点的值 大于等于 其子节点。
    • 堆顶元素 是最大值。

2. 堆的存储方式

堆通常使用 数组 存储,并且满足:

  • 父节点parent(i) = (i - 1) / 2
  • 左子节点left(i) = 2 * i + 1
  • 右子节点right(i) = 2 * i + 2

3. Java 中的堆(PriorityQueue)

Java 提供了 PriorityQueue 实现最小堆:

import java.util.PriorityQueue;

PriorityQueue<Integer> minHeap = new PriorityQueue<>(); // 默认最小堆
minHeap.offer(5);
minHeap.offer(2);
minHeap.offer(8);

System.out.println(minHeap.poll()); // 输出 2(最小值)

如果要创建最大堆:

PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);

第 K 大的元素

题目描述

给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

注意

  • 你需要找的是数组排序后的 第 k 个最大的元素,而不是第 k 个不同的元素。
  • 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例

输入

nums = [3,2,1,5,6,4], k = 2

输出

5

使用堆求解第 K 大的元素

1. 方法概述

使用 最小堆(Min Heap) 可以高效地求解 第 K 大的元素,该方法的核心思想是维护一个大小为 k最小堆,其中堆顶元素始终是当前 前 K 大元素 中的最小值。


2. 解题思路

  1. 创建一个大小为 k 的最小堆PriorityQueue)。
  2. 遍历数组 nums
    • 如果 堆的大小小于 k,则直接将当前元素 num 插入堆中。
    • 如果 堆的大小等于 k
      • 只有当 num > 堆顶元素 时,才将堆顶元素移除,并插入 num
  3. 遍历结束后,堆顶元素即为第 k 大的元素

3. 代码实现

import java.util.PriorityQueue;

class Solution {
    public int findKthLargest(int[] nums, int k) {
        // 创建一个最小堆(容量为 k)
        PriorityQueue<Integer> minHeap = new PriorityQueue<>(k);

        // 遍历数组
        for (int num : nums) {
            if (minHeap.size() < k) { 
                // 直接入堆
                minHeap.offer(num);
            } else if (num > minHeap.peek()) { 
                // 只在当前元素比堆顶元素大的时候进行替换
                minHeap.poll();
                minHeap.offer(num);
            }
        }
        // 堆顶即为第 k 大的元素
        return minHeap.peek();
    }
}

前 K 个高频元素

1. 题目描述

给定一个整数数组 nums 和一个整数 k,要求找出 出现频率最高的 K 个元素。返回顺序可以 任意


2. 解题思路

  1. 使用 HashMap 统计元素频率:遍历数组,记录每个数字的出现次数。
  2. 构建最小堆(小根堆):维护大小为 K 的最小堆,堆顶存储当前出现频率最低的元素
  3. 遍历 HashMap 并更新堆
    • 若堆的大小小于 k,则直接加入堆。
    • 若新元素的频率 大于堆顶元素的频率,则替换堆顶元素并调整堆。
  4. 堆中存储的即是前 K 个高频元素

3. 代码实现

使用 PriorityQueue(Java 默认最小堆)

import java.util.*;

class Solution {
    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. 使用最小堆存储前 K 个高频元素
        PriorityQueue<int[]> minHeap = new PriorityQueue<>(Comparator.comparingInt(a -> a[1]));

        for (Map.Entry<Integer, Integer> entry : freqMap.entrySet()) {
            int num = entry.getKey(), freq = entry.getValue();
            if (minHeap.size() < k) {
                minHeap.offer(new int[]{num, freq});
            } else if (freq > minHeap.peek()[1]) {
                minHeap.poll(); // 移除频率最小的
                minHeap.offer(new int[]{num, freq});
            }
        }

        // 3. 取出堆中的元素
        int[] result = new int[k];
        for (int i = 0; i < k; i++) {
            result[i] = minHeap.poll()[0];
        }
        return result;
    }
}

Map.Entry<K, V> 介绍

  • Map.Entry<K, V>Java Map 接口的内部接口,表示 Map 中的 键值对(key-value)
  • entrySet() 方法返回 包含所有键值对 (Entry) 的集合,然后可以用 for-each 遍历。

entrySet() 作用

freqMap.entrySet() 返回一个 Set<Map.Entry<K, V>>,其中:

  • 每个 Entry<K, V> 代表 一个键值对
  • getKey() 获取键(数字)。
  • getValue() 获取值(出现的次数)。

Comparator.comparingInt(a -> a[1])

在 Java 中,Comparator.comparingInt(a -> a[1]) 用于创建一个 基于数组元素的某个索引值进行排序 的比较器,主要用于 PriorityQueue(优先队列) 或 Collections.sort()。
Comparator.comparingInt(a -> a[1])

  • comparingInt(ToIntFunction<T> keyExtractor):Comparator 提供的 辅助方法,用于按照 int 类型的键排序。
  • a -> a[1]Lambda 表达式,指定对 a 这个数组的 索引 1 位置的值进行排序。

http://www.kler.cn/a/539024.html

相关文章:

  • android的Compose 简介
  • 迁移学习 Transfer Learning
  • 物联网软件开发与应用方向应该怎样学习,学习哪些内容,就业方向是怎样?(文末领取整套学习视频,课件)物联网硬件开发与嵌入式系统
  • 基于python多线程多进程爬虫的maa作业站技能使用分析
  • 灵巧手技术全景解析:从仿生设计到智能控制
  • 基于DeepSeek API和VSCode的自动化网页生成流程
  • 智慧城市节水管理信息系统项目解决方案
  • 在阿里云ECS上一键部署DeepSeek-R1
  • 7.Python文件操作:文件的打开与关闭、文件的读写、文件读写应用
  • 数据管理的“圣经”——《DAMA数据管理知识体系指南(第二版)》
  • 解锁 DeepSeek 模型高效部署密码:蓝耘平台深度剖析与实战应用
  • React 什么是抽象组件及为什么要抽象组件
  • 人工智能-A* 算法规划的路径进行动态调整
  • 分组加密算法CLEFIA
  • 【LLM】o1/R1系列LLM数据篇
  • 【开学补课复习专题】python 语言考试试题2
  • cuda学习资料汇总
  • 第六届MathorCup高校数学建模挑战赛-A题:淡水养殖池塘水华发生及池水自净化研究
  • C++ 实现封装的顺序表:顺序表的操作与实践
  • 浏览器的缓存方式几种
  • 基于Java的在线购物系统的设计与实现
  • 【hive】记一次hiveserver内存溢出排查,线程池未正确关闭导致
  • C++ 中信号转异常机制:在磁盘 I/O 内存映射场景下的应用与解析
  • 49-拓展(1)
  • Docker 部署 verdaccio 搭建 npm 私服
  • Prompt逆向工程:如何“骗“大模型吐露其Prompt?