5.1-2 用random(0,1)来实现random(a,b),并估计运行时间.
想到一种解法,分治法:
1.分解,将a-b区间分成2部分,通过random(0,1)控制,则进入前半部和后半部的概率是一样的;
2.递归的处理前后两个部分,若问题足够小,即落到某个具体位置上时,则直接返回;
伪代码:
int random( a, b )
{
if( a == b )
return a;
if( random( 0, 1 ) )
return random( a, (a+b)/2 );
else
return random( (a+b)/2 + 1, b );
}
但仔细分析下发现有问题.
令 n = b-a, 问题简化为 1/n = f( 1/(2^x) ),
root
/ \
0 1
/ \ / \
/ ..... \
0 ......... 1
时间复杂度为 O(lgn),通过lgn次random(0,1)调用,即生成长度为lg(b-a)的"前后后前..."随机序列来控制最后落定的位置,类似2叉决策树的决策过程,x次random(0,1)调用最多可能产生2^x条路径,即最多可能返回2^x种结果,每条路径的产生概率相等,即1/(2^x).
但如果n不是2的整数次方,不可能将概率平均分配到每条路径,所以不可能在有限次调用内生成精确的平均返回概率.
如, n=8时,可以取x=3,正好8种返回结果的概率一样,都是1/8.但如果n=7,那么b的返回概率可能会是2/8,其余值的返回概率均为1/8.
所以得到的结果是不精确的,上网查了很久,也没找到答案 |