use*_*222 1 algorithm recursion probability
function foo(n)
if n = 1 then
return 1
else
return foo(rand(1, n))
end if
end function
Run Code Online (Sandbox Code Playgroud)
如果最初使用m作为参数调用foo,那么调用rand()的预期次数是多少?
BTW,rand(1,n)返回1到n范围内的均匀分布的随机整数.
一个简单的例子是计算所需的调用次数f(2).说这个时间是x,那么x = 1 + 0/2 + x/2因为我们做了实际的呼叫1,然后1/2我们有概率地去,f(1)并且1/2我们留下概率f(2).解决这个等式给了我们x = 2.
与大多数递归的运行时分析一样,我们尝试获得运行时的递归公式.我们可以使用期望的线性来进行随机调用:
E[T(1)] = 0
E[T(2)] = 1 + (E[T(1)] + E[T(2)])/2 = 2
E[T(n)] = 1 + (E[T(1)] + E[T(2)] + ... E[T(n)])/n
= 1 + (E[T(1)] + E[T(2)] + ... E[T(n-1)])/n + E[T(n)]/n
= 1 + (E[T(n-1)] - 1)(n-1)/n + E[T(n)]/n
Run Code Online (Sandbox Code Playgroud)
于是
E[T(n)](n-1) = n + (E[T(n-1)] - 1)(n-1)
Run Code Online (Sandbox Code Playgroud)
因此,对于n> 1:
E[T(n)] = 1/(n-1) + E[T(n-1)]
= 1/(n-1) + 1/(n-2) + ... + 1/2 + 2
= Harmonic(n-1) + 1
= O(log n)
Run Code Online (Sandbox Code Playgroud)
这也是我们直觉可能预期的结果,因为n每次调用大约应该有一半f.
我们也可以考虑"最有可能的最坏情况".为此,使用Markov的不等式很容易P[X <= a*E[X]] >= 1-1/a.设置a = 100我们以99%的概率得到它,算法比100 * log n调用少rand.