算法第四版35页问题1.1.27,估计用一下代码计算binomial(100,50,0.25)将会产生的递归调用次数:算法
public static double binomial(int n,int k,double p){ if(n == 0 && k == 0) return 1.0; if(n<0 || k<0) return 0.0; return (1.0-p)*binomial(n-1,k,p) +p*binomial(n-1,k-1,p) }
虽然书上只让估计调用次数,可是以为想知道到底调用了几回。函数
我用图画出递归调用的状况spa
能够看出递归中有不少重复调用好比,第4层递归 分别调用了binomial(n-3,k-1,p)和binomial(n-3,k-2,p)三次。这就是这个算法效率低的缘由。能够看出重复调用的次数是一个杨辉三角。3d
根据杨辉三角的性质,code
第m层递归函数被调用的状况为:blog
第m层第x(x<=m)项为:递归
可是有些调用实际上不会发生,结合函数的返回条件:get
if(n == 0 && k == 0) return 1.0; if(n<0 || k<0) return 0.0;
设咱们传入的初始参数为n=N,k=K 则,能够得出已下结论:it
让咱们看看知足以上结论的详细项:class
1.下列递归调用的x>K+1,知足结论2:
2.m=N+1行的第K+1项递归调用的第一个参数n和第二个参数k均为0,知足结论1。
3.当m=N+2时,显然m>N+1,知足结论2;
若是调用参数知足函数退出条件,那么由
调用的递归实际上就不会发生,数量为
的系数✖️2。
N+2以后的递归都不会发生,因此作计算时只考虑到N+2层。N+2层的无效调用数量,为N+1层知足结论1或2的调用的数量*2,一次类推,直到K+3层的无效调用数量,为K+2层知足结论1或2的调用数量*2;K+2层到1层上,全部调用都有效;由于K+1层到1层,没有调用知足结论1或2.
根据杨辉三角的性质:从第1层到第N+2层全部的系数和为
其中不会实际发生的调用次数为从(K+2层到N+1层):
化简以后为:
再次化简
因此最后程序递归调用的总次数为
运行随机验证几个组合,能够证实上述公式是正确的!