Java 详细讲解用堆解决Top-k问题

Java 详细讲解用堆解决Top-k问题

问题描述

Top-k问题常常需解决业务中的热点,如商品销量排行、热搜关键词、热门文章等。假定要找出一个无序数组中前k大或前k小的元素,解决此问题有多种方法,下面我们主要介绍用堆排序算法解决Top-k问题。

思路及实现

1. 思路

用堆排序算法的思路如下:

  1. 建立一个大小为k的堆,如果堆里面元素数量未达到k,那么将当前元素加入堆中即可
  2. 如果当前元素大于堆顶元素,那么将堆顶元素替换成当前元素
  3. 遍历完整个数组后,堆中的元素就是前k大或前k小的元素

用大根堆求前k大的数,用小根堆求前k小的数。

2. 实现

下面是用Java实现Top-k问题的示例代码:

public class TopK {
    /**
     * 求数组中前k大的数
     *
     * @param nums 数组
     * @param k    k的大小
     * @return 前k大元素的List
     */
    public List<Integer> getTopK(int[] nums, int 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);
            }
        }

        return new ArrayList<>(minHeap);
    }

    /**
     * 求数组中前k小的数
     *
     * @param nums 数组
     * @param k    k的大小
     * @return 前k小元素的List
     */
    public List<Integer> getLowK(int[] nums, int k) {
        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);
            }
        }

        return new ArrayList<>(maxHeap);
    }
}

上面代码中,我们用Java内置的优先队列PriorityQueue来实现堆排序,函数offer()用于插入堆中元素,函数poll()用于删除堆顶元素,而peek()则用于查看堆顶元素而不删除它。

接下来我们用一个数组和getTopK()函数来演示求前k大的数:

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

    TopK topK = new TopK();
    List<Integer> topKList = topK.getTopK(nums, k);

    System.out.println("前" + k + "大的的数为:" + topKList.toString());
}

控制台输出结果为:前4大的的数为:[3, 4, 5, 6],即数组中前4大的数是3, 4, 5, 6。

接着,我们来演示用getLowK()函数来求前k小的数:

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

    TopK topK = new TopK();
    List<Integer> lowKList = topK.getLowK(nums, k);

    System.out.println("前" + k + "小的的数为:" + lowKList.toString());
}

控制台输出结果为:前4小的的数为:[1, 0, 2, 3],即数组中前4小的数是1, 0, 2, 3。

以上示例代码和输出结果,均说明用堆排序算法可以很方便地解决Top-k问题。

小结

用堆排序算法解决Top-k问题,是一种时间复杂度为O(nlogk)的高效算法,它也是解决业务中Top-k问题的常用方法之一。

我们注意到PriorityQueue由于使用了大常数,堆排序的复杂度与快速排序相近:O(n * logn),但优于冒泡排序的O(n^2)。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 详细讲解用堆解决Top-k问题 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Python实现链表反转的方法分析【迭代法与递归法】

    Python实现链表反转的方法分析 链表是一种数据结构,它由一系列节点构成,每个节点包含一个值和指向下一个节点的指针。如果想要对链表进行操作,例如删除、插入或者反转等等,那么就需要了解如何正确地遍历链表。 本文将详细介绍Python实现链表反转的两种方法:迭代法和递归法,内容包括基础原理、代码实现以及示例说明。 基础原理 链表反转是指将链表中元素的前后顺序颠…

    other 2023年6月27日
    00
  • Android 调用系统相机拍摄获取照片的两种方法实现实例

    Android 调用系统相机拍摄获取照片的两种方法实现实例 在 Android 开发中,我们经常需要调用系统相机来拍摄照片。下面将详细介绍两种方法来实现这个功能,并提供示例代码。 方法一:使用 Intent 调用系统相机应用 这种方法是最简单的方式,通过创建一个 Intent 对象并指定相机动作,然后启动系统相机应用。相机应用会处理拍摄照片的过程,并将结果返…

    other 2023年8月21日
    00
  • React组件的生命周期详细描述

    React组件的生命周期是指组件从被创建(Mount)到销毁(Unmount)的整个过程中的各个阶段。了解这些阶段对于理解React的运行机制和编写高质量的React应用程序非常重要。下面是React组件的生命周期详细描述攻略。 概述 React组件的生命周期可以划分为三个阶段: 挂载(Mounting)阶段:组件被创建并插入到DOM中。 更新(Updati…

    other 2023年6月27日
    00
  • Spark SQL操作JSON字段的小技巧

    Spark SQL操作JSON字段的小技巧 Spark SQL是在Spark中操作结构化和半结构化数据的一种高级数据处理技术。Spark SQL可以轻松地与JSON数据交互,而JSON数据是Web应用程序开发中非常常见的一种数据格式。在本文中,我们将讨论如何使用Spark SQL操作JSON数据。 加载JSON文件 首先,我们需要从文件系统或外部数据源中加载…

    other 2023年6月26日
    00
  • C#栈

    C#栈 C#(读作C Sharp),是一门由微软开发的面向对象的、类型安全的、现代化的程序设计语言。C#语言丰富的库和框架,使它成为了Windows平台上广受欢迎的一门语言。本文将介绍C#中的栈(Stack)数据结构以及相关的应用。 栈的介绍 栈是一种“先进后出”(Last In First Out, LIFO)的数据结构。栈的基本操作有入栈(push)和出…

    其他 2023年3月28日
    00
  • 用 win2003 架设共享服务器 的图文教程

    下面我将详细讲解“用 win2003 架设共享服务器 的图文教程”的完整攻略: 一、安装文件共享服务 在 Windows Server 2003 中,文件共享服务可以通过“控制面板”>“添加/删除程序”>“添加/删除 Windows 组件”选项安装。在“添加 Windows 组件”窗口中,勾选“文件服务器”并单击“下一步”按钮。然后按照向导的提示…

    other 2023年6月28日
    00
  • 关于protected修饰符详解-源于Cloneable接口

    下面就来详细讲解一下“关于protected修饰符详解-源于Cloneable接口”的完整攻略。 1. protected修饰符的作用 protected 修饰符用于类的成员变量,方法及构造方法,可以让子类访问并修改原本属于父类的该成员变量、方法及构造方法。在同一个包中的其他类中,也可以访问 protected 成员。 2. protected修饰符的使用限…

    other 2023年6月27日
    00
  • Dreamweaver工作区布局有哪些工具?

    Dreamweaver工作区布局的工具 Dreamweaver是一款功能强大的网页设计和开发工具,它提供了多种工具和功能来帮助用户创建和编辑网页。下面是Dreamweaver工作区布局中的一些常用工具: 文件管理器:文件管理器位于左侧面板,用于浏览和管理项目文件。您可以在文件管理器中创建、删除和重命名文件夹和文件,以及导入和导出文件。 代码编辑器:代码编辑器…

    other 2023年9月5日
    00
合作推广
合作推广
分享本页
返回顶部