热门标签 | 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));}

 


推荐阅读
  • 数据输入验证与控件绑定方法
    本文提供了多种数据输入验证函数及控件绑定方法的实现代码,包括电话号码、数字、传真、邮政编码、电子邮件和网址的验证,以及报表绑定和自动编号等功能。 ... [详细]
  • 1、编写一个Java程序在屏幕上输出“你好!”。programmenameHelloworld.javapublicclassHelloworld{publicst ... [详细]
  • 编码unicode解决了语言不通的问题.但是.unicode又有一个新问题.由于unicode是万国码.把所有国家的文字都编进去了.这就导致一个unicode占用的空间会很大.原来 ... [详细]
  • 解析Java虚拟机HotSpot中的GC算法实现
    本文探讨了Java虚拟机(JVM)中HotSpot实现的垃圾回收(GC)算法,重点介绍了根节点枚举、安全点及安全区域的概念和技术细节,以及这些机制如何影响GC的效率和准确性。 ... [详细]
  • 本文基于Java官方文档进行了适当修改,旨在介绍如何实现一个能够同时处理多个客户端请求的服务端程序。在前文中,我们探讨了单客户端访问的服务端实现,而本篇将深入讲解多客户端环境下的服务端设计与实现。 ... [详细]
  • 探讨 try-finally 结构中 finally 块的执行情况
    本文深入分析了 Java 中 try-finally 结构的执行机制,特别是探讨了在不同情况下 finally 块是否会得到执行。 ... [详细]
  • ArcBlock 发布 ABT 节点 1.0.31 版本更新
    2020年11月9日,ArcBlock 区块链基础平台发布了 ABT 节点开发平台的1.0.31版本更新,此次更新带来了多项功能增强与性能优化。 ... [详细]
  • 在开发过程中,有时需要提供用户创建数据库的功能。本文介绍了如何利用 .NET 和 ADOX 在应用程序中实现创建 Access 数据库,并详细说明了创建数据库及表的具体步骤。 ... [详细]
  • 视觉Transformer综述
    本文综述了视觉Transformer在计算机视觉领域的应用,从原始Transformer出发,详细介绍了其在图像分类、目标检测和图像分割等任务中的最新进展。文章不仅涵盖了基础的Transformer架构,还深入探讨了各类增强版Transformer模型的设计思路和技术细节。 ... [详细]
  • D17:C#设计模式之十六观察者模式(Observer Pattern)【行为型】
    一、引言今天是2017年11月份的最后一天,也就是2017年11月30日,利用今天再写一个模式,争取下个月(也就是12月份& ... [详细]
  • 贡献转移在计算每个元素的作用的时候,我们可以通过反向枚举作用效果,添加到作用元素的身上,这种方法叫做贡献转移。更正式的说, ... [详细]
  • 基于SSM框架的在线考试系统:随机组卷功能详解
    本文深入探讨了基于SSM(Spring, Spring MVC, MyBatis)框架构建的在线考试系统中,随机组卷功能的设计与实现方法。 ... [详细]
  • 本文介绍了MySQL窗口函数的基本概念、应用场景及常见函数的使用方法。窗口函数在处理复杂查询时非常有用,例如计算每个用户的订单排名、环比增长率、以及动态聚合等。 ... [详细]
  • Spring Security基础配置详解
    本文详细介绍了Spring Security的基础配置方法,包括如何搭建Maven多模块工程以及具体的安全配置步骤,帮助开发者更好地理解和应用这一强大的安全框架。 ... [详细]
  • binlog2sql,你该知道的数据恢复工具
    binlog2sql,你该知道的数据恢复工具 ... [详细]
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社区 版权所有