算法搬运之BFPRT算法
原文连接:http://noalgo.info/466.html
BFPRT算法,又称为中位数的中位数算法,由5位大牛(Blum 、 Floyd 、 Pratt 、 Rivest 、 Tarjan)提出,并以他们的名字命名。参考维基上的介绍Median of medians。
算法的思想是修改快速选择算法的主元选取方法,提高算法在最坏情况下的时间复杂度。其主要步骤为:
首先把数组按5个数为一组进行分组,最后不足5个的忽略。对每组数进行排序(如插入排序)求取其中位数。
把上一步的所有中位数移到数组的前面,对这些中位数递归调用BFPRT算法求得他们的中位数。
将上一步得到的中位数作为划分的主元进行整个数组的划分。
判断第k个数在划分结果的左边、右边还是恰好是划分结果本身,前两者递归处理,后者直接返回答案。
首先看算法的主程序,代码如下。小于5个数的情况直接处理返回答案。否则每5个进行求取中位数并放到数组前面,递归调用自身求取中位数的中位数,然后用中位数作为主元进行划分。
注意这里只利用了中位数的下标,而不关心中位数的数值,目的是方便在划分函数中使用下标直接进行交换。BFPRT算法执行完毕之后可以保证我们想要的数字是排在了它真实的位置上,所以可以直接使用中位数的下标。
int BFPRT(int a[], int l, int r, int id) //求数组a下标l到r中的第id个数
{
if (r - l + 1 <= 5) //小于等于5个数,直接排序得到结果
{
insertionSort(a, l, r); return a[l + id - 1];
}
int t = l - 1; //当前替换到前面的中位数的下标
for (int st = l, ed; (ed = st + 4) <= r; st += 5) //每5个进行处理
{
insertionSort(a, st, ed); //5个数的排序
t++; swap(a[t], a[st+2]); //将中位数替换到数组前面,便于递归求取中位数的中位数
}
int pivotId = (l + t) >> 1; //l到t的中位数的下标,作为主元的下标
BFPRT(a, l, t, pivotId-l+1);//不关心中位数的值,保证中位数在正确的位置
int m = partition(a, l, r, pivotId), cur = m - l + 1;
if (id == cur) return a[m]; //刚好是第id个数
else if(id < cur) return BFPRT(a, l, m-1, id);//第id个数在左边
else return BFPRT(a, m+1, r, id-cur); //第id个数在右边
}
这里的划分函数与之前稍微不同,因为指定了划分主元的下标,所以参数增加了一个,并且第一步需要交换主元的位置。代码如下:
int partition(int a[], int l, int r, int pivotId) //对数组a下标从l到r的元素进行划分
{
//以pivotId所在元素为划分主元
swap(a[pivotId],a[r]);
int j = l - 1; //左边数字最右的下标
for (int i = l; i < r; i++)
if (a[i] <= a[r])
swap(a[++j], a[i]);
swap(a[++j], a[r]);
return j;
}
这里简单分析一下BFPRT算法的复杂度。
划分时以5个元素为一组求取中位数,共得到n/5个中位数,再递归求取中位数,复杂度为T(n/5)。
得到的中位数x作为主元进行划分,在n/5个中位数中,主元x大于其中1/2*n/5=n/10的中位数,而每个中位数在其本来的5个数的小组中又大于或等于其中的3个数,所以主元x至少大于所有数中的n/10*3=3/10*n个。同理,主元x至少小于所有数中的3/10*n个。即划分之后,任意一边的长度至少为3/10,在最坏情况下,每次选择都选到了7/10的那一部分,则递归的复杂度为T(7/10*n)。
在每5个数求中位数和划分的函数中,进行若干个次线性的扫描,其时间复杂度为c*n,其中c为常数。其总的时间复杂度满足 T(n) <= T(n/5) + T(7/10*n) + c * n。
我们假设T(n)=x*n,其中x不一定是常数(比如x可以为n的倍数,则对应的T(n)=O(n^2))。则有 x*n <= x*n/5 + x*7/10*n + c*n,得到 x<=10*c。于是可以知道x与n无关,T(n)<=10*c*n,为线性时间复杂度算法。而这又是最坏情况下的分析,故BFPRT可以在最坏情况下以线性时间求得n个数中的第k个数。
算法搬运之BFPRT算法的更多相关文章
- (搬运)《算法导论》习题解答 Chapter 22.1-1(入度和出度)
(搬运)<算法导论>习题解答 Chapter 22.1-1(入度和出度) 思路:遍历邻接列表即可; 伪代码: for u 属于 Vertex for v属于 Adj[u] outdegre ...
- BFPRT算法
解决的问题:在一个数组中找到最小的k个数 常规解法:1.排序,输出前k个数,时间复杂度O(n*log(n)). 2.利用一个大小为k的大根堆,遍历数组维持大根堆,最后返回大根堆就可以了,时间复杂度O( ...
- 查找第K小的数 BFPRT算法
出处 http://blog.csdn.net/adong76/article/details/10071297 BFPRT算法是解决从n个数中选择第k大或第k小的数这个经典问题的著名算法,但很多人并 ...
- 算法进阶面试题02——BFPRT算法、找出最大/小的K个数、双向队列、生成窗口最大值数组、最大值减最小值小于或等于num的子数组数量、介绍单调栈结构(找出临近的最大数)
第二课主要介绍第一课余下的BFPRT算法和第二课部分内容 1.BFPRT算法详解与应用 找到第K小或者第K大的数. 普通做法:先通过堆排序然后取,是n*logn的代价. // O(N*logK) pu ...
- 经典算法 BFPRT算法详解
内容: 1.原始问题 => O(N*logN) 2.BFPRT算法 => O(N) 1.原始问题 问题描述:给你一个整型数组,返回其中第K小的数 普通解法: 这道题可以利用 ...
- Top K问题-BFPRT算法、Parition算法
BFPRT算法原理 在BFPTR算法中,仅仅是改变了快速排序Partion中的pivot值的选取,在快速排序中,我们始终选择第一个元素或者最后一个元素作为pivot,而在BFPTR算法中,每次选择五分 ...
- 荷兰国旗问题、快排以及BFPRT算法
荷兰国旗问题 给定一个数组arr,和一个数num,请把小于num的数放数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边.要求额外空间复杂度O(1),时间复杂度O(N). 这个问题 ...
- BFPRT算法(求第K小的数字)
BFPRT算法: 1.介绍: BFPRT算法又叫中位数的中位数算法,主要用于在无序数组中寻找第K大或第K小的数,它的最坏时间复杂度为O(n),它是由Blum,Floyd,Pratt,Rivest,Ta ...
- KMP算法和bfprt算法总结
目录 1 KMP算法 1.1 KMP算法分析 1.2 KMP算法应用 题目1:旋转词 题目2:子树问题 2 bfprt算法 2.1 bfprt算法分析 2.2 bfprt算法应用 1 KMP算法 大厂 ...
随机推荐
- Mac上传文件到Linux服务器
1. 打开 终端,选择 2.选择安全文件传输,输入连接主机IP 3.输入主机名 4.输入yes,然后输入主机密码,按回车结束 确认连接 输入远程主机密码 5.连接成功,上传文件 put 本地文件路径 ...
- Android学习笔记_79_ Android 使用 搜索框
1.在资源文件夹下创建xml文件夹,并创建一个searchable.xml: android:searchSuggestAuthorityshux属性的值跟实现SearchRecentSuggesti ...
- Oracle数据库对象,同义词、序列、视图、索引
数据库对象简介 Oracle 数据库对象又称模式对象 数据库对象是逻辑结构的集合,最基本的数据库对象是表 其他数据库对象包括: 同义词是现有对象的一个别名. 简化SQL语句 隐藏对象的名称和所有者 提 ...
- 122. Best Time to Buy and Sell Stock II ——LeetCode
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...
- sudoers文件解析 转自:http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=1971013
今天在用户组中新加了一个普通用户,开始这个用户没有sudo权限,于是通过sudo visudo修改了sudo的配置文件,赋予了普通用户的root权限.后来想着能不能将/etc/sudoers文件的访问 ...
- SQL0668N 不允许对表XX执行操作,原因码为 "3"
DB2 Load导入数据失败之后,表被锁,提示,SQL0668N 不允许对表XX执行操作,原因码为 "3". 之前也遇到过,当时都是现查现用的,现在在博客记一下,以备后查. 解决方 ...
- 2 3 5 7的倍数 (51Nod - 1284)[容斥定理]
20180604 给出一个数N,求1至N中,有多少个数不是2 3 5 7的倍数. 例如N = 10,只有1不是2 3 5 7的倍数. Input 输入1个数N(1 <= N <= 10^1 ...
- 【例题收藏】◇例题·6◇ 电压机制(voltage)
◆例题·6◆ 电压机制 周六日常模拟赛……已经不知道该说什么了(感觉做不出来的都是好题) ▷ 题目 (终于不用自己翻译英文题了╮(╯-╰)╭) [问题描述] 科学家在“无限神机”(Infinity M ...
- 在CentOS 7上搭建Docker环境
Preface We commonly use VMware or VirtualBox to install our Virtual Machines before.For the ...
- linux系统下病毒排除思路
1.top查看是否有特别吃cpu和内存的进程,病毒进程kill是杀不死的,因为ps命令被修改 2.ls -la /proc/病毒进程pid/ pwd为病毒进程程序目录 一般在/usr/bin下 3. ...