Select 选择算法 - 编程珠玑(续) 笔记
Select 算法
I 编程珠玑(续)介绍的 Quickselect 算法
选择 N 个元素中的第 K 小(大)值,是日常场景中常见的问题,也是经典的算法问题.
选取 N 个元素的数组的中的第 K 小(大)值,最简单的想法是将数组排序后直接选取. 那么这种方法的时间复杂度是O(N log N).
C.A.R.Hoare 提出的 Quickelect 算法的平均时间复杂度达到了 O(N) . 在去递归之后, 是原地算法. 这个算法因为其简洁,高效而被广泛使用.
算法思路的C++实现如下.
int select(vector<int>& X, int k) {
int l = 0, u = X.size() - 1;
while(l < u){
swap(X[l], X[rand()%(u-l+1)+l]);
int m = l;
for(int i = l + 1; i <= u; i++)
if(X[i] < X[l])
swap(X[++m], X[i]); //m在i遍历的过程中,是遍历过的元素中, 小于X[l]的元素的最大下标
swap(X[l], X[m]);
if(k <= m) u = m - 1;
if(k >= m) l = m + 1;
}
return X[k];
}
- 当 k 选定为数组的中位数时,平均所耗的时间最多.
- 当数组中有大量重复元素,或者是逆序排序的数组时,会增加运行时间. 遇到大量重复的元素时不能很快地缩小 l - u 的范围. 逆序数组会产生很多的 swap 操作.
- Worst-case peformance O(N ^ 2)
II 序列输入时使用的 Heap-Select 算法
考虑一个输入序列,要求在序列输入完毕的时候得出这个序列的第 k 大(小)的元素.
要选择第 k 小的元素时, 我们考虑用一个 k 大小的大顶堆. 对数组从头开始遍历(等价于数组线性输入), 头 k 个元素用于建立 k 大小的大顶堆. 对于从 k + 1 到 N 的元素. 当该元素小于堆顶元素的时候,将该元素插入到堆中,将堆顶元素出堆. 遍历(输入)结束后, 堆顶元素即为我们要找的元素.
相应的选择第 k 大的元素时, 我们考虑用一个 k 大小的小顶堆.对数组从头开始遍历. 头 k 个元素用于建立 k 大小的小顶堆. 对于从 k + 1 到 N 的元素. 当该元素大于堆顶元素的时候,将该元素插入到堆中,将堆顶元素出堆. 遍历(输入)结束后, 堆顶元素即为我们要找的元素.
这样可得这个算法的时间复杂度为 O(k) + O(N * log k) ==> O(N * log k)
由于要调用空间构造堆,空间复杂度为 O(k)
关于这个算法的正确性,用归纳法, 从已经输入k的数组中挑选头k个最大(小)的元素。 然后继续下去即可。
III 三个元素的中间值
杀鸡不用牛刀,三个元素的中间值用简单的三次比较就可以搞定.
if(X[1] > X[2])
swap(X[1], X[2]);
if(X[2] > X[3])
swap(X[2], X[3]);
if(X[1] > X[2])
swap(X[1], X[2]); //自此 X[1], X[2], X[3] 从小到大有序.
IV 其他的Select算法
Median of medians 又名 BFPRT算法. 基于Blum, Floyd, Pratt, Rivest and Tarjan 1973年的论文 Time Bounds for Selection. 拥有O(N) 的 worst case performance.
Introselect 则是BFPRT算法和 Quickselect 算法的结合. 默认使用 Quickselect ,在 Quickselect 表现出比较差的运行情况时转向Median of medians. 从而也能提供O(N) 的 worst case performance.
Select 选择算法 - 编程珠玑(续) 笔记的更多相关文章
- 算法线性编程珠玑读书笔记之----->使用线性算法求解连续子序列的最大和
这段时间笔者几篇文章介绍了改算法线性的文章. 关联文章的地址 这个算法我在我的博客里应用动态规划做过,详细实现请参阅我的dp板块,下面给出书上最快的算法,时间复杂度为O(n),称之为线性算法. #in ...
- 学习笔记之编程珠玑 Programming Pearls
Programming Pearls (2nd Edition): Jon Bentley: 0785342657883: Amazon.com: Books https://www.amazon.c ...
- 《编程珠玑,字字珠玑》读书笔记完结篇——AVL树
写在最前面的 手贱翻开了<珠玑>的最后几章,所以这一篇更多是关于13.14.15章的内容.这篇文章的主要内容是“AVL树”,即平衡树,比红黑树低一个等次.捣乱真惹不起红黑树,情况很复杂:而 ...
- 读书笔记--编程珠玑II
学化学的应该都知道chemdraw,这是一款专门绘制化学结构的软件,什么苯环.双键各种word难以搞定的分子式,你可以轻松的用chemdraw完成,可以称得上化学工作者居家旅行必备的良药.其实早在19 ...
- 编程珠玑I算法总结
主要是根据编程珠玑后面的Algorithm附录总结了一下这本书里面的经典算法. 1 辗转相减求最大公约数 思想:最大公约数能整除i和j,则其一定也能整除i-j(if i>j) int gcd(i ...
- 一种最坏情况线性运行时间的选择算法 - The missing worst-case linear-time Select algorithm in CLRS.
一种最坏情况线性运行时间的选择算法 - The missing worst-case linear-time Select algorithm in CLRS. 选择算法也就是求一个无序数组中第K大( ...
- python核心编程第二版笔记
python核心编程第二版笔记由网友提供:open168 python核心编程--笔记(很详细,建议收藏) 解释器options:1.1 –d 提供调试输出1.2 –O 生成优化的字节码(生成 ...
- 《[MySQL技术内幕:SQL编程》读书笔记
<[MySQL技术内幕:SQL编程>读书笔记 2019年3月31日23:12:11 严禁转载!!! <MySQL技术内幕:SQL编程>这本书是我比较喜欢的一位国内作者姜承尧, ...
- 《C#高级编程》读书笔记
<C#高级编程>读书笔记 C#类型的取值范围 名称 CTS类型 说明 范围 sbyte System.SByte 8位有符号的整数 -128~127(−27−27~27−127−1) sh ...
随机推荐
- nessus 漏洞扫描安装和使用
介绍 Nessus 是目前全世界最多人使用的系统漏洞扫描与分析软件.总共有超过75,000个机构使用Nessus 作为扫描该机构电脑系统的软件. 软件特色 * 提供完整的电脑漏洞扫描服务, 并随时更 ...
- 架构思想之CAP原理
由于自己负责后端的设计已经有一段时间,对设计的一些思想和理论有一些理解,但最近被问到什么是CAP时,却一脸懵逼,下来后专门针对CAP架构思想进行了一些专题学习,在这里也将这个概念引入给大家,大家可以有 ...
- Mysql学习总结(25)——MySQL外连接查询
1.左外连接left outer join或者left jion,outer可以省略不写,下边的右连接和全连接也一样: 左外连接的意思是,以left join左边的表中的数据为基准,即左边的表中有的必 ...
- 基于Core Text实现的TXT电子书阅读器
本篇文章的项目地址基于Core Text实现的TXT电子书阅读器. 最近花了一点时间学习了iOS的底层文字处理的框架Core Text.在网上也参考很多资料,具体的资料在文章最后列了出来,有兴趣的可参 ...
- 4.有关日期格式属性改动常识,v$nls_parameters,between and,查询指定部门的员工信息,in和null,like模糊查询,order by后面能够跟:列名、表达式、别名、序号
1 有关日期格式属性改动常识 NLS_DATE_FORMAT DD-MON-RR select sysdate from dual; NLS_CURRENCY ...
- java匿名内部类的使用注意事项
1.首先匿名内部类要继承自抽象基类或者实现基类接口 like this abstract class Seed{ int cnt; public Seed(int x){ cnt=x; } abstr ...
- angularjs 路由 ngRoute tab切换
<!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="C ...
- Numpy科学计算工具
Numpy初探 Numpy基础数据结构 Numpy数组是一个多维数组,称为ndarray.其由两部分组成: 实际的数据 描述这些数据的原数据 导入该库: import numpy as np 多维数组 ...
- mysql InnoDB引擎 共享表空间和独立表空间(转载)
PS:innodb这种引擎,与MYISAM引擎的区别很大.特别是它的数据存储格式等.对于innodb的数据结构,首先要解决两个概念性的问题: 共享表空间以及独占表空间. 1.什么是共享表空间和独占表空 ...
- Android框架-Volley(三)
经过前面两篇文章的学习,我们已经掌握了Volley各种Request的使用方法,包括StringRequest.JsonRequest.ImageRequest等.其中StringRequest用于请 ...