从一个序列里面选择第k大的数在没有学习算法导论之前我想最通用的想法是给这个数组排序,然后按照排序结果返回第k大的数值。如果使用排序方法来做的话时间复杂度肯定至少为O(nlgn)。

问题是从序列中选择第k大的数完全没有必要来排序,可以采用分治法的思想解决这个问题。Randomize select 算法的期望时间复杂度可以达到O(n),这正是这个算法的迷人之处。具体的算法分析可以在《算法导论》这本书里查看。

贴出伪代码:

  1. RANDOMIZED-SELECT(A, p, r, i)
  2. if p = r
  3. then return A[p]
  4. q RANDOMIZED-PARTITION(A, p, r)
  5. k q - p +
  6. if i = k the pivot value is the answer
  7. then return A[q]
  8. elseif i < k
  9. then return RANDOMIZED-SELECT(A, p, q - , i)
  10. else return RANDOMIZED-SELECT(A, q + , r, i - k)

这个算法的思想其实跟quik-sort有些相似,采用分治法的思想来解决。首先选择一个主元pirvot: q,将序列中的元素分为两个集合Q,W,Q里面的元素都小于主元pirvot,W里面的元素都大于pirvot。然后递归的调用这个过程可以得到我们想要的第i大的元素。这里的划分有三种情况:

1:主元的选择正好是第i大的元素,那么返回这个元素即可

2:Q里面的元素个数 k=(q-p+1) 大于i,代表第i大的元素还在Q这个集合里,那么继续这个过程寻找第i小的元素( step 7-8)

3:Q里面的元素个数 k=(q-p+1) 小于i,代表已经找到了k个小的元素,那么第i小的元素一定在W这个集合里,只要在W集合里寻找第(i-k)小的元素即可

下面给出这个算法的java实现:

  1. /**
  2. * 根据算法导论的伪代码,完成快速选择的代码。
  3. * @author 截取自:http://blog.csdn.net/zy825316/article/details/19486167
  4.  
  5. */
  6. public class randomizedSelect {
  7.  
  8. /**
  9. * @param args
  10. */
  11. public static void main(String[] args) {
  12. int a[]={,,,,,,,};
  13.  
  14. int result=randomizedSelect(a,,a.length-,);//产生第三小的数
  15. System.out.print("\n"+result);
  16. }
  17.  
  18. private static int partition(int[] a, int p, int r) {
  19. int x=a[r];
  20. int i=p-;
  21. for(int j=p;j<r;j++){
  22. if(a[j]<=x){
  23. i=i+;
  24. swap(a, i, j);
  25. }
  26. }
  27. swap(a, i+, r);
  28. return i+;
  29. }
  30.  
  31. private static int randomizedPartition(int[] a,int p,int r){
  32. java.util.Random random = new java.util.Random();
  33. int i=Math.abs(random.nextInt() % (r-p+)+p);//产生指定范围内的随机数
  34. swap(a,i,r);
  35. return partition(a,p,r);
  36. }
  37.  
  38. /**
  39. *
  40. * @param a 数组
  41. * @param p 数组的第一个元素
  42. * @param r 数组的最后一个元素
  43. * @param i 需要求第几小的元素
  44. * @return
  45. */
  46. private static int randomizedSelect(int[] a,int p,int r,int i){
  47. if(p==r){
  48. return a[p];//这种情况就是数组内只有一个元素
  49. }
  50. int q=randomizedPartition(a,p,r);
  51. int k=q-p+;//拿到上一句中作为枢纽的数是第几小的数
  52. if(i==k){
  53. return a[q];
  54. }else if(i<k){
  55. return randomizedSelect(a,p,q-,i);
  56. }else{
  57. return randomizedSelect(a,q+,r,i-k);
  58. }
  59.  
  60. }
  61.  
  62. private static void swap(int[] a, int i, int j) {
  63. int temp=a[i];
  64. a[i]=a[j];
  65. a[j]=temp;
  66. }
  67.  
  68. }

Randomize select algorithm 随机选择算法的更多相关文章

  1. 使用Numpy验证Google GRE的随机选择算法

    最近在读<SRE Google运维解密>第20章提到数据中心内部服务器的负载均衡方法,文章对比了几种负载均衡的算法,其中随机选择算法,非常适合用 Numpy 模拟并且用 Matplotli ...

  2. 一种最坏情况线性运行时间的选择算法 - The missing worst-case linear-time Select algorithm in CLRS.

    一种最坏情况线性运行时间的选择算法 - The missing worst-case linear-time Select algorithm in CLRS. 选择算法也就是求一个无序数组中第K大( ...

  3. 用Python实现随机森林算法,深度学习

    用Python实现随机森林算法,深度学习 拥有高方差使得决策树(secision tress)在处理特定训练数据集时其结果显得相对脆弱.bagging(bootstrap aggregating 的缩 ...

  4. Bagging与随机森林算法原理小结

    在集成学习原理小结中,我们讲到了集成学习有两个流派,一个是boosting派系,它的特点是各个弱学习器之间有依赖关系.另一种是bagging流派,它的特点是各个弱学习器之间没有依赖关系,可以并行拟合. ...

  5. [Machine Learning & Algorithm] 随机森林(Random Forest)

    1 什么是随机森林? 作为新兴起的.高度灵活的一种机器学习算法,随机森林(Random Forest,简称RF)拥有广泛的应用前景,从市场营销到医疗保健保险,既可以用来做市场营销模拟的建模,统计客户来 ...

  6. [Data Structure & Algorithm] 八大排序算法

    排序有内部排序和外部排序之分,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.我们这里说的八大排序算法均为内部排序. 下图为排序 ...

  7. R语言︱决策树族——随机森林算法

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 笔者寄语:有一篇<有监督学习选择深度学习 ...

  8. R语言︱机器学习模型评估方案(以随机森林算法为例)

    笔者寄语:本文中大多内容来自<数据挖掘之道>,本文为读书笔记.在刚刚接触机器学习的时候,觉得在监督学习之后,做一个混淆矩阵就已经足够,但是完整的机器学习解决方案并不会如此草率.需要完整的评 ...

  9. Python机器学习笔记——随机森林算法

    随机森林算法的理论知识 随机森林是一种有监督学习算法,是以决策树为基学习器的集成学习算法.随机森林非常简单,易于实现,计算开销也很小,但是它在分类和回归上表现出非常惊人的性能,因此,随机森林被誉为“代 ...

随机推荐

  1. linux 命令 备忘

    openssl rand -base64 32 随机数 date | md5sum data 日期 cal 日历 man -f man sync 数据同步写入磁盘 shutdown reboot ha ...

  2. 关于Java中try-catch-finally-return语句的思考

    我们知道return语句用在某一个方法中,一是用于返回函数的执行结果,二是用于返回值为void类型的函数中,仅仅是一个return语句(return ;),此时用于结束方法的执行,也即此return后 ...

  3. MAT使用总结

    最近在做项目的时候遇到一个内存泄漏,最后通过MAT定位了问题, 先介绍一下MAT的一些基本概念: Shallow Heap:对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员变量(不是 ...

  4. POJ 3904 Sky Code

    题意:给定n个数ai, ai <= 10000, n <= 10000, 从中选出4个数要求gcd为1,这样的集合有多少个? 分析:首先总共集合nCr(n, 4) = n*(n-1)*(n ...

  5. linux 2.6 互斥锁的实现-源码分析

    http://blog.csdn.net/tq02h2a/article/details/4317211 看了看linux 2.6 kernel的源码,下面结合代码来分析一下在X86体系结构下,互斥锁 ...

  6. ajax跨域访问的解决方案

    今天的工作中要访问摄像机内部的一个web站点,这就涉及到jquery的ajax跨域访问的问题.我使用的是jquery1.7的版本,下面总结如下: 问题一:一开始用IE调试,总是返回No Transpo ...

  7. Firefox Security Toolkit 安装

    目的: 下载Firefox Security Toolkit加载到浏览器里,增强渗透测试的工具利用. 兼容性: 目前仅支持Linux/Unix环境(可在kali上安装使用). 下载安装: wget h ...

  8. GPRS连接失败问题

    备注:采用的是SIMCOM的SIM900模块 1. GPRS连接失败问题 2013.08.06测试9台C2000两次,两次之间是机器拿开电池,间隔40分钟左右,每次都出现一台(但不是同一台): ⑴9台 ...

  9. poj3275

    比较笨啊,一直在想,到底问几次绝对能知道所有的关系呢? 后来看了题解才知道,问一次最少确定一对关系………… 这就好办le,n头牛有C(2,n)个关系 现在给出m条边,以确定的关系有多少呢?直接dfs啊 ...

  10. [原]Unity3D深入浅出 - 认识开发环境中的Layers面板

    Layers(分层)下拉列表:用来控制Scene视图中游戏对象的显示,在下拉菜单中为勾选状态的物体将显示在Scene视图中. Everything:显示所有的游戏对象 Nothing:不显示任何游戏对 ...