關於用遞歸實現的二項分佈算法
最近在看Sedgewick的《算法》的時候有一題習題是關於改進用遞歸實現的二項分佈算法。這裏我令服從二項分佈爲$X\sim b(N,k,p)$,書本上習題給出的算法是:
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-p)*binomial(N-1,k,p)+p*binomial(N-1,k-1,p);
}
我們可能剛開始看這個遞歸算法的時候會不太明白(當時我都看懵逼了),那我們就從小一點的值來分析一下,假如
我們可以看到每一次都可以分開兩部分然後再繼續遞歸,直到出現
你就會懂爲什麼有這個遞推算法了,而且上面的公式本質上其實是組合遞推公式:
那麼我們搞懂了這個算法之後,我們會發現這個算法在
所以後來就改了一下算法,改用大量循環,不用遞歸實現。
//計算組合數
public static double zuhe(double N, double k)
{
//模擬人類計算的約分過程從而減少階乘數量
double m = N-k;
double min = k;
double max = m;
double t = 0;
double NN=1;
double kk=1;
if(min>max)
{
t=min;
min = max;
max=t;
}
//把大的階乘約分去掉
while(N>max)
{
NN=NN*N;
N--;
}
//計算小的階乘
while(min>0)
{
kk=kk*min;
min--;
}
//算出組合數
return NN/kk;
}
//計算二項分佈值
public static double binomial(int N,int k,double p)
{
double y=1;
double s=1;
//計算組合數
double a =binomial(N,k);
//計算(1-p)的(N-k)次方
while((N-k)>0)
{
s=s*(1-p);
N--;
}
//計算p的k次方
while(k>0)
{
y=y*p;
k--;
}
//最後三個值相乘得出二項分佈值
return a*y*s;
}
}
經過去掉遞歸後的算法就能很快的算出
如果你們還有更好的算法,可以告訴我,大家交流一下學習一下。