斐波那契數(shù)列算法問題(最優(yōu)可達對數(shù)階)

????????有一個大家都很熟悉的經(jīng)典數(shù)學(xué)問題,即斐波那契數(shù)列算法問題。這個經(jīng)典案例在算法中又會變成什么樣子呢?


int fib(int n){?

????if(n?==?0)

????????return 0;

????if(n?==?1)

????????return 1;

????return fib(n - 1)+fib(n - 2);

}


? ? ? ? 首先,我們很容易使用遞歸算法來設(shè)計該算法。但是計算出結(jié)果是一個指數(shù)階的算法,當(dāng)n到100的時候,每多算一個斐波那契數(shù)需要至少多算一年。

? ? ? ? 那我們今天就主要介紹一下優(yōu)化后的算法。

????????算法優(yōu)化1:每次記錄前兩項的值,只需要一次加法運算得到當(dāng)前項,算法時間復(fù)雜度降低到了O(n),效率大幅度提高。

????????算法改進2:使用迭代法,兩數(shù)輾轉(zhuǎn)相加,每次記錄前一項,時間復(fù)雜度為O(n),空間復(fù)雜度降低到了O(1)。代碼如下:


int fib(int n){

????int i , s1 = 1 , s2 = 1;

????if(n < 1)

????????return -1;

????if(n == 1 || n == 2)

????????return 1;

????for(i = 3;i <= n; i++){

????????s1 = s1 + s2;

????????s1 = s2 - s1;

????}

????return s2;

}


????????算法改進3:接下來我們來看看對數(shù)階的斐波那契數(shù)列算法。先來看下面這種算法:


int fib(int n){

????return fib_iter(1,0,n);

}

int fib_iter(a,b,count){

? ??if(count == 0)

? ??????return b;

? ??return fib_iter(a+b , a,? count - 1);

}


????????在這種算法中,我們每次遞歸都將a+b的值賦給a,把a的值賦給b,通過觀察可以發(fā)現(xiàn),從1和0開始將規(guī)則反復(fù)應(yīng)用n次,將產(chǎn)生一對數(shù)fib(n)和fib(n+1),現(xiàn)在將這種規(guī)則看成a = bq + aq + a*pb = bp + aq其中p=0,q=1把這種變換稱為T變換,

Tpq 變換有個特性是 Tpq 的二次方等于Tp‘q’, p‘ = pp + qq , q' = 2pq + q*q

即:a = (bp+aq)p+(bq+aq+ap)q+(bq+aq+ap)p = b(2pq+q^2)+a(p^2+2pq+2q^2)

b = (bp+aq)p+(bq+aq+ap)q = b(p^2+q^2)+a(q^2+2pq)

此處p=0,q=1


int fib(int n){

????return fib_iter(1,0,0,1,n);

}

int fib_iter(int a,int b,int p,int q,int count){

????if (count == 0)

????????return b;

else? if (count%2)

????return fib_iter(b*p+a*q+a*p,b*p+a*q,p,q,count-1);

else

????return fib_iter(a,b,p*p+q*q,q*q+2*p*q,count/2);

}


這樣的算法時間復(fù)雜度可以達到對數(shù)階。大幅地提高了算法的效率。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容