Randomize select algorithm 随机选择算法

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

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

贴出伪代码:


RANDOMIZED-SELECT(A, p, r, i)
1 if p = r
2 then return A[p]
3 q ← RANDOMIZED-PARTITION(A, p, r)
4 k ← q - p + 1
5 if i = k ? the pivot value is the answer
6 then return A[q]
7 elseif i < k
8 then return RANDOMIZED-SELECT(A, p, q - 1, i)
9 else return RANDOMIZED-SELECT(A, q + 1, 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实现:


/**
* 根据算法导论的伪代码,完成快速选择的代码。
* @author 截取自:http://blog.csdn.net/zy825316/article/details/19486167

*/
public class randomizedSelect {

/**
* @param args
*/
public static void main(String[] args) {
int a[]={2,5,3,0,2,3,0,3};

int result=randomizedSelect(a,0,a.length-1,3);//产生第三小的数
System.out.print("\n"+result);
}

private static int partition(int[] a, int p, int r) {
int x=a[r];
int i=p-1;
for(int j=p;j<r;j++){
if(a[j]<=x){
i=i+1;
swap(a, i, j);
}
}
swap(a, i+1, r);
return i+1;
}

private static int randomizedPartition(int[] a,int p,int r){
java.util.Random random = new java.util.Random();
int i=Math.abs(random.nextInt() % (r-p+1)+p);//产生指定范围内的随机数
swap(a,i,r);
return partition(a,p,r);
}

/**
*
* @param a 数组
* @param p 数组的第一个元素
* @param r 数组的最后一个元素
* @param i 需要求第几小的元素
* @return
*/
private static int randomizedSelect(int[] a,int p,int r,int i){
if(p==r){
return a[p];//这种情况就是数组内只有一个元素
}
int q=randomizedPartition(a,p,r);
int k=q-p+1;//拿到上一句中作为枢纽的数是第几小的数
if(i==k){
return a[q];
}else if(i<k){
return randomizedSelect(a,p,q-1,i);
}else{
return randomizedSelect(a,q+1,r,i-k);
}

}

private static void swap(int[] a, int i, int j) {
int temp=a[i];
a[i]=a[j];
a[j]=temp;
}

}

Randomize select algorithm 随机选择算法,布布扣,bubuko.com

时间: 2024-10-25 12:38:34

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

算法系列笔记2(静态表顺序统计-随机选择算法)

问题:当给定存在静态表(如数组)中的n个元素,如何快速找到其中位数.最小值.最大值.第i小的数? 首先想到的方法是先对数组元素进行排序,然后找到第i小的元素.这样是可行的,但比较排序最快也需要O(nlgn),能否在线性时间内解决呢.这就是随机的分治法-随机选择. 思想:利用随机划分(在快速排序中介绍过)找到主元r,这样就将小于等于r的元素放在了其左边,大于r的元素放在了其右边.这是可以计算出r的rank为k,如果正好等于i,则就返回该元素:如果k大于i,则在左边中寻找第i小的元素,否则在右边中寻

随机选择算法

随机选择算法和快速排序原理相似,所以有时候也称作“快速选择算法”,一般选择问题可以证明都能在O(n)时间内完成.随机选择算法的期望运行时间为线性时间,即Θ(n),但其最坏情况运行时间为O(n^2).最坏情况与快排一样,都是运气不好导致划分不均匀. 代码: #include "stdafx.h" #include <iostream> #include <vector> #include <stdlib.h> class QuicklySelect {

线性选择算法(未完成)

#include "stdafx.h" #include<iostream> #include <stdlib.h> #include <time.h> using namespace std; #define SB -1 int RANDOM(int p, int r) { srand((unsigned)time(NULL)); return (rand() % (r - p + 1)) + p; } int partition(int a[],

c2java select algorithm

对于很多应用来说,随机算法是最简单的或者最快的.既简单又快的有没有呢? 那需要深刻的洞察力或者革命性的突破. 什么是随机算法 随机算法与确定算法区别是:它还接收输入随机比特流来做随机决策. 对于同一个输入,每次运行所用的算法行为都不同,虽然结果都是一样的. Foiling an adversary 可以构造一个输入使得一个确定性算法运行时间最长. 随机算法可以看作是从一族算法中随机选出来的一个算法. 快速排序O(NlgN)的精髓在于随机化划分. 快速的意思是常数因子是1.38. 标准库里面采用小

我的游戏服务器类库 -- 按权重随机选择1个或n个对象

按权重选择 在编写游戏服务器的时候,经常会遇到类似的需求:从列表中随机选出1个或多个条目,且条目是有权重的(权重越大,选中它的可能性就越大).比如说,砍死一个怪物可以从一个装备列表里掉一个装备.这种需求,和现实生活中的幸运大转盘很类似: 算法实现 因为这种需求很常见,所以我想把它写的通用一点.首先,接口Weighted表示有权重值的对象,getWeight()方法返回权重值: public interface Weighted { public int getWeight(); } Weight

查询反模式 - 随机选择

一.问题提出 随机数在数据库中是经常用到的系统. 例如,一个广告系统希望随机选择一个广告来显示.随机推荐相关文章等等. 在SQL Server中查找随机数最简单的方法为: SELECT TOP 1 * FROM Person ORDER BY NEWID() 以上SQL语句的执行计划如下: 以上这种方法,需要对整个表进行一次排序,而且还无法有效地使用索引.加入我们只需要前几条数据,那么好不容易对整个结果集完成了排序,但绝大多数都浪费了. 以上的方式缺点如下: 随着数据量的增加,随机数的产生会变慢

最坏情况为线性的选择算法

基本思想 主体上是在期望为线性的选择算法上进行改进,将其中的随机的划分元素改为取中位数,使划分更均匀,从而达到最坏时时间复杂度也为线性.需要注意的是实现时里面的索引很晕,别搞混了.我就是先写了个很乱,然后实在改不下去了,就重写了,总共我大概写了5,6个小时吧.(可能我太菜了) 图解 代码 伪代码 这里书中未给伪代码,仅给了整个算法的流程,但并不影响我们的实现 C代码 #include <stdio.h> #define N 50 void show(int *a, int p, int r);

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

在集成学习原理小结中,我们讲到了集成学习有两个流派,一个是boosting派系,它的特点是各个弱学习器之间有依赖关系.另一种是bagging流派,它的特点是各个弱学习器之间没有依赖关系,可以并行拟合.本文就对集成学习中Bagging与随机森林算法做一个总结. 随机森林是集成学习中可以和梯度提升树GBDT分庭抗礼的算法,尤其是它可以很方便的并行训练,在如今大数据大样本的的时代很有诱惑力. 1.  bagging的原理 在集成学习原理小结中,我们给Bagging画了下面一张原理图. 从上图可以看出,

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

笔者寄语:有一篇<有监督学习选择深度学习还是随机森林或支持向量机?>(作者Bio:SebastianRaschka)中提到,在日常机器学习工作或学习中,当我们遇到有监督学习相关问题时,不妨考虑下先用简单的假设空间(简单模型集合),例如线性模型逻辑回归.若效果不好,也即并没达到你的预期或评判效果基准时,再进行下换其他更复杂模型来实验. ---------------------------------------------- 一.随机森林理论介绍 1.1 优缺点 优点. (1)不必担心过度拟合