java 最大Topk 小跟堆 最小Topk 大跟堆 详解

Python3.8

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

在 Java 中,寻找 最大 Top K最小 Top K 的元素通常使用 优先队列(PriorityQueue)。具体来说:

  1. 最大 Top K:用一个小根堆(PriorityQueue 默认是小根堆)保存当前最大的 K 个元素。
  2. 最小 Top K:用一个大根堆(通过 Comparator 实现)保存当前最小的 K 个元素。

核心思路

  • 小根堆:用于维护最大 Top K。

    • 堆中始终保留 K 个元素,当新元素大于堆顶时替换堆顶,重新调整堆。
    • 堆顶始终是当前 K 个最大元素中的最小值。
  • 大根堆:用于维护最小 Top K。

    • 堆中始终保留 K 个元素,当新元素小于堆顶时替换堆顶,重新调整堆。
    • 堆顶始终是当前 K 个最小元素中的最大值。

代码实现

1. 最大 Top K(使用小根堆)

import java.util.PriorityQueue;

public class TopKMax {
    public static void main(String[] args) {
        int[] nums = {3, 2, 1, 5, 6, 4, 8, 9, 7};
        int k = 3; // 找最大的 Top 3

        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); // 插入新元素
            }
        }

        // 输出结果:堆中存储的就是最大 Top K
        System.out.println("最大 Top " + k + ": " + minHeap);
    }
}
关键点解析
  1. PriorityQueue<Integer> 默认是小根堆,peek() 获取堆顶(最小值)。
  2. 每次插入新元素时,堆中只保留 K 个最大的元素,堆顶是当前 Top K 最大中的最小值。
输出示例
最大 Top 3: [7, 8, 9]

2. 最小 Top K(使用大根堆)

import java.util.PriorityQueue;
import java.util.Collections;

public class TopKMin {
    public static void main(String[] args) {
        int[] nums = {3, 2, 1, 5, 6, 4, 8, 9, 7};
        int k = 3; // 找最小的 Top 3

        PriorityQueue<Integer> maxHeap = new PriorityQueue<>(k, Collections.reverseOrder()); // 大根堆

        for (int num : nums) {
            if (maxHeap.size() < k) {
                maxHeap.offer(num); // 堆未满,直接加入
            } else if (num < maxHeap.peek()) {
                maxHeap.poll(); // 弹出最大值
                maxHeap.offer(num); // 插入新元素
            }
        }

        // 输出结果:堆中存储的就是最小 Top K
        System.out.println("最小 Top " + k + ": " + maxHeap);
    }
}
关键点解析
  1. PriorityQueue<>(k, Collections.reverseOrder()) 创建大根堆。
  2. 每次插入新元素时,堆中只保留 K 个最小的元素,堆顶是当前 Top K 最小中的最大值。
输出示例
最小 Top 3: [2, 1, 3]

3. 扩展:返回结果的排序

默认情况下,堆中的元素顺序不保证是从大到小或从小到大。如果需要结果有序,可以将堆元素导出后排序:

对最大 Top K 排序
import java.util.*;

public class Main {
    public static void main(String[] args) {
        int[] nums = {3, 2, 1, 5, 6, 4, 8, 9, 7};
        int k = 3;

        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);
            }
        }

        // 转换为有序结果
        List<Integer> result = new ArrayList<>(minHeap);
        Collections.sort(result, Collections.reverseOrder()); // 从大到小排序
        System.out.println("最大 Top " + k + " (有序): " + result);
    }
}
输出示例
最大 Top 3 (有序): [9, 8, 7]

时间复杂度分析

假设数组大小为 nnn,需要找 Top kkk 个元素:

  1. 堆操作

    • 插入(offer)和删除(poll)的时间复杂度为 O(log⁡k)O(\log k)O(logk)
    • 对于 nnn 个元素,最多进行 nnn 次堆操作,时间复杂度为 O(nlog⁡k)O(n \log k)O(nlogk)
  2. 排序(可选)

    • 如果需要对结果排序,复杂度为 O(klog⁡k)O(k \log k)O(klogk)
  3. 总复杂度

    • 不需要排序:O(nlog⁡k)O(n \log k)O(nlogk)
    • 需要排序:O(nlog⁡k+klog⁡k)O(n \log k + k \log k)O(nlogk+klogk)

总结

  1. 最大 Top K(小根堆)

    • 使用 PriorityQueue 默认实现,堆顶是当前 K 个最大值中的最小值。
  2. 最小 Top K(大根堆)

    • 使用 PriorityQueue + Collections.reverseOrder() 创建大根堆,堆顶是当前 K 个最小值中的最大值。
  3. 效率

    • 堆的实现非常高效,适合处理大规模数据。
    • 若 K 远小于 N,使用堆的方式比全排序更优。
  4. 排序结果

    • 如果需要有序的 Top K 结果,可以将堆内容导出到列表并排序。

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞滕人生TYF

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值