[算法]由random(0,1)生成random(a,b)

问题描述:

描述RANDOM(a,b)过程的一种实现,它只调用RANDOM(0,1)。作为a和b的函数,你的程序期望运行时间是多少?

这是算法导论上的一道题。

这个没有固定答案,看了很多网上的解法之后,总结一下我的想法。首先,random(0,1)是随机的产生0,1两个整数,random(a,b)是随机产生[a,b]之间的整数。随机就是等概率的意思。生成random(a,b)等价于随机生成[0,b-a]内的一个数,然后在加上a就是[a,b]之间的数了。

解法一:

设k=b-a,假设2的c次方(以下用2^c表示)是第一个大于b-a的2的正整数次方,那么调用random(0,1)c次,产生一个c位的二进制数,对应一个[0,2^c-1]的十进制数,如果这个数在[0,b-a]之内,输出,否则继续生成c位二进制数,直到得到一个[0,b-a]之内的数为止。

下面是java代码的表示:

public int randomAB2(int a,int b){
        int k=b-a;
        //找到第一个2^n大于k的n
        int k1=k;
        int c=0;
        while(k1!=0){
            c++;
            k1=(int)Math.floor(k1/2);
        }
        int s=0;
        //生成0到k的数
        do{
            s=0;
            for(int i=0;i<c;i++){
                s+=random01()*Math.pow(2, i);
            }
        }
        while(s>k);
        return s+a;
    }

期望运行时间:

第二个while循环的运行次数呈几何分布,每一次成功(也就是得到了[0,b-a]之内的数)的概率是---p=(b-a+1)/(2^c),这里的c应该是lg(b-a)向上取整,所以运行次数的期望是Tavg=1/p。

期望运行时间T(a,b)=Tavg*lg(b-a)*D。其中lg(b-a)是以2为底b-a的对数,D是第二个while循环内代码运行的时间,是个常数。这个貌似是个O(lg(b-a))级别的运行时间。

解法二:

这个方法来自http://blog.csdn.net/longhuihu/article/details/5864442这篇博文的解法一。这个方法也是先生成一个长度为k=b-a+1二进制序列---R1,R2,..,然后把二进制序列中值为0对应的[0,b-a]中的数删除,从而减小要生成数的范围。

下面是模拟这个过程的java代码:

View Code
public int randomAB(int a,int b){
        int k=b-a+1;
        ArrayList<Integer> S=new ArrayList<Integer>();
        ArrayList<Integer> temS;
        for(int i=0;i<k;i++){
            S.add(i);
        }
        temS=copy(S);
        while(S.size()>1){
            int n=S.size();
            for(int j=n-1;j>=0;j--){
                int r=random01();
                if(r==0){
                    temS.remove(j);
                }
            }
            if(temS.isEmpty()){
                temS=copy(S);
            }
            else{
                S=temS;
                temS=copy(S);
            }
        }
        return S.get(0)+a;
    }

这个理解起来比较容易,但是分析期望运行时间比较复杂。

首先,要生成几次b-a+1长度的二进制序列才能达到缩减范围的目的?这也是个几何分布,每次试验成功的概率是p=1-2/2^k(因为只要不生成全0或全1就会成功)。那么试验次数的期望是Tavg=1/p。那么运行时间T(a,b)可以表示为T(a,b)=Tavg*k*D+T(x)。这个T(x)表示任何可能的缩小范围后的范围,x取值在1-(k-1)之间,D是循环内的常数运行时间。

这篇文章证明了这种做法最后输出的a,b之间的数肯定是等概率的,应用了数学归纳法,证明方法如下:

(1)能够等概率生成0,1

(2)假设有random(m),m<k等概率生成0-m之间的数。

(3)证明random(k)生成[0,k-1]之间的数也是等概率的:

定义事件:

Ai--输出第i个数

Bim--一轮筛选后m个数留下,其中包含第i个数

 

P(Ai|Bim)=random(m)=1/m,这是(2)的假设。

P(Ai,Bim)=P(Bim)*P(Ai|Bim)=P(Bim)*(1/m)。

P(Bim)=C((k-1),(m-1))/(2k-2)。C((k-1),(m-1))是个组合公式。

P(Ai)=∑P(Ai,Bim) for m=1:(k-1)。这是个求和公式,对m从1到k-1取值求和。

求解后的P(Ai)=1/k。

 

 

 

 

 

posted @ 2013-04-13 22:41  orchid  阅读(3299)  评论(2编辑  收藏  举报