热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

算法TOPK(BFPRT算法)JAVA版本

一、背景在一大堆数中求其前k大或前k小的问题,简称TOP-K问题。而目前解决TOP-K问题最有效的算法即是BFPRT算法,其又称为中位数的中位数算法&

一、背景

在一大堆数中求其前k大或前k小的问题,简称TOP-K问题。而目前解决TOP-K问题最有效的算法即是BFPRT算法,其又称为中位数的中位数算法,该算法由Blum、Floyd、Pratt、Rivest、Tarjan提出,最坏时间复杂度为O(n)O(n)。

在首次接触TOP-K问题时,我们的第一反应就是可以先对所有数据进行一次排序,然后取其前k即可,但是这么做有两个问题: 
(1):快速排序的平均复杂度为O(nlogn)O(nlogn),但最坏时间复杂度为O(n2)O(n2),不能始终保证较好的复杂度。 
(2):我们只需要前k大的,而对其余不需要的数也进行了排序,浪费了大量排序时间。

除这种方法之外,堆排序也是一个比较好的选择,可以维护一个大小为k的堆,时间复杂度为O(nlogk)O(nlogk)。

那是否还存在更有效的方法呢?受到快速排序的启发,通过修改快速排序中主元的选取方法可以降低快速排序在最坏情况下的时间复杂度(即BFPRT算法),并且我们的目的只是求出前k,故递归的规模变小,速度也随之提高。下面来简单回顾下快速排序的过程,以升序为例: 
(1):选取主元(首元素,尾元素或一个随机元素); 
(2):以选取的主元为分界点,把小于主元的放在左边,大于主元的放在右边; 
(3):分别对左边和右边进行递归,重复上述过程。
原文链接:https://blog.csdn.net/laojiu_/article/details/54986553

    仅用荷兰国旗算法也能达到数学期望为O(N)的时间复杂度,但是也有可能存在O(N2)的最差情况,BFPRT就是在荷兰国旗算法的基础上,加入寻找一个好的中位数,让时间复杂度稳定在O(N)

二、算法套路

BFPRT算法套路
1. 对整个数组进行分组,每组5个数,不满5个的凑成最后一组
2.对每个组进行组内排序, 时间复杂度O(N)
    为什么时间复杂度O(N),解释:
    排序算法时间复杂度为O(NlogN), 当N等于5时候,即为O(1)
    对N/5个数组进行排序,所以时间复杂度为O(N)
3.拿出排序后的每个数组的中位数,组成一个新的N/5长度数组
4.递归掉BFPRT
5.拿到BFPRT的返回的num, 小于放左边,等于放中间,大于放右边。即快排里的荷兰国旗pattition算法。

伪代码:

int bfprt(int[] arr, int k){
    1.
    2.
    3.生成一个N/5大小的new_arr
    4.bfprt(new_arr, new_arr.length/2);
    5.
}

三、代码

public static int[] getMinKNumsByBFPRT(int[] arr, int k) {if (k <1 || k > arr.length) {return arr;}int minKth &#61; getMinKthByBFPRT(arr, k);int[] res &#61; new int[k];int index &#61; 0;for (int i &#61; 0; i !&#61; arr.length; i&#43;&#43;) {if (arr[i] &#61; pivotRange[0] && i <&#61; pivotRange[1]) {return arr[i];} else if (i pivotValue) {swap(arr, cur, --big);} else {cur&#43;&#43;;}}int[] range &#61; new int[2];range[0] &#61; small &#43; 1;range[1] &#61; big - 1;return range;}public static int getMedian(int[] arr, int begin, int end) {insertionSort(arr, begin, end);int sum &#61; end &#43; begin;int mid &#61; (sum / 2) &#43; (sum % 2);return arr[mid];}public static void insertionSort(int[] arr, int begin, int end) {for (int i &#61; begin &#43; 1; i !&#61; end &#43; 1; i&#43;&#43;) {for (int j &#61; i; j !&#61; begin; j--) {if (arr[j - 1] > arr[j]) {swap(arr, j - 1, j);} else {break;}}}}public static void swap(int[] arr, int index1, int index2) {int tmp &#61; arr[index1];arr[index1] &#61; arr[index2];arr[index2] &#61; tmp;}public static void printArray(int[] arr) {for (int i &#61; 0; i !&#61; arr.length; i&#43;&#43;) {System.out.print(arr[i] &#43; " ");}System.out.println();}public static void main(String[] args) {int[] arr &#61; { 6, 9, 1, 3, 1, 2, 2, 5, 6, 1, 3, 5, 9, 7, 2, 5, 6, 1, 9 };// sorted : { 1, 1, 1, 1, 2, 2, 2, 3, 3, 5, 5, 5, 6, 6, 6, 7, 9, 9, 9 }printArray(getMinKNumsByBFPRT(arr, 10));}

 


推荐阅读
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • Java 类成员初始化顺序与数组创建
    本文探讨了Java中类成员的初始化顺序、静态引入、可变参数以及finalize方法的应用。通过具体的代码示例,详细解释了这些概念及其在实际编程中的使用。 ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • 本文详细介绍了 Dockerfile 的编写方法及其在网络配置中的应用,涵盖基础指令、镜像构建与发布流程,并深入探讨了 Docker 的默认网络、容器互联及自定义网络的实现。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 在金融和会计领域,准确无误地填写票据和结算凭证至关重要。这些文件不仅是支付结算和现金收付的重要依据,还直接关系到交易的安全性和准确性。本文介绍了一种使用C语言实现小写金额转换为大写金额的方法,确保数据的标准化和规范化。 ... [详细]
  • PHP 编程疑难解析与知识点汇总
    本文详细解答了 PHP 编程中的常见问题,并提供了丰富的代码示例和解决方案,帮助开发者更好地理解和应用 PHP 知识。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • Windows服务与数据库交互问题解析
    本文探讨了在Windows 10(64位)环境下开发的Windows服务,旨在定期向本地MS SQL Server (v.11)插入记录。尽管服务已成功安装并运行,但记录并未正确插入。我们将详细分析可能的原因及解决方案。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 数据管理权威指南:《DAMA-DMBOK2 数据管理知识体系》
    本书提供了全面的数据管理职能、术语和最佳实践方法的标准行业解释,构建了数据管理的总体框架,为数据管理的发展奠定了坚实的理论基础。适合各类数据管理专业人士和相关领域的从业人员。 ... [详细]
  • 前言--页数多了以后需要指定到某一页(只做了功能,样式没有细调)html ... [详细]
  • 探讨一个显示数字的故障计算器,它支持两种操作:将当前数字乘以2或减去1。本文将详细介绍如何用最少的操作次数将初始值X转换为目标值Y。 ... [详细]
author-avatar
国民男神-权志龙
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有