斐波那契數列的研究

2021-06-22 06:35:51 字數 2801 閱讀 6914

讀昨天剛買的《android應用效能優化》,第一章介紹了斐波那契數列的實現及優化,這是演算法方面的問題。

斐波那契數列,又稱**分割數列,指的是這樣乙個數列:0、1、1、2、3、5、8、13、21、……在數學上,斐波納契數列以如下被以遞迴的方法定義:f0=0,f1=1,fn=f(n-1)+f(n-2)(n>=2,n∈n*)

書中介紹了4種實現,頭兩種是遞迴,後面兩種是迭代。當然迭代更好,因為遞迴效率低下,可能導致棧溢位。

public static long computerecursively(int n)

第一種很好理解,不用多說,後面的三種,很費力的研究了許久。

第二種是對第一種的優化,見下,每次呼叫少遞迴呼叫一次:

public static long computerecursivelywithloop(int n) while(n>1);

return result;

} return n;

}

分析:看起來就像是從第n-2個值開始累加到第乙個,在額外加上個1,就是第n個值。

f(n) = f(n-2) +  f(n-1)每次都把上次分解得到的較大的乙個(即每行的最後乙個)進行再分解,得到f(n) = sum(f(n-2) + ... +f(0)) + 1

= f(n-2) + f(n-3) + f(n-2)

= f(n-2) + f(n-3) + f(n-4) + f(n-3)

= f(n-2) + f(n-3) + f(n-4) + (f(n-5)+f(n-4))

= f(n-2) + f(n-3) + f(n-4) + f(n-5) + f(n-6) + f(n-5)

= ...

= f(n-2) + f(n-3) + ... + f(2) + f(3)

= f(n-2) + f(n-3) + ... + f(2) + f(1) + f(2)

= f(n-2) + f(n-3) + ... + f(2) + f(1) + f(0) + f(1)

= sum(f(n-2) + ... + f(0)) + 1

剩下的兩種迭代實現的方法也是這個求和的原理,方法3如下:

public static long computeiteratively(int n)while(--n>1);

return b;

} return n;

}

0	1	2	3	4	5	6	7	8

0 1 1 2 3 5 8 13 21

0 a b

1 a b

2 a b

3 a b

4 a b

5 a b

6 a b

7 a b

經歷n-1次迴圈, f(n) = b

方法4每次迭代計算兩項,迭代總數與方法3相比少了一半:

根據n奇偶判斷初值,如果n是奇數,則a=0, b=1;如果n是偶數則a=1,b=1

public static long computeiterativelyfaster(int n)

return b;

} return n;

}

自己根據方法4寫了自以為更容易理解的:

0	1	2	3	4	5	6	7	8

0 1 1 2 3 5 8 13 21

0 a b

1 a b

2 a b

3 a b

4 a b

經歷n/2次迴圈, 如果n為奇數,f(n)=b; 如果n為偶數,f(n)=a

public static long computeiterativelyfaster2(int n)

}if(evenodd==0)else

} return n;

}

關於溢位:

long型有64位,除去第一位是符號位,最大值為9223372036854775807。

可容納的最大的斐波那契數是7540113804746346429,即第92項。

寫的方法裡做了檢測,當溢位的時候,跳出,檢視當前的a、b值,及迴圈次數。

執行結果:

當n=30的時候,

long_max:9223372036854775807

f[30]

832040

5ms832040

4ms832040

0ms832040

0ms832040

0ms當n=100的時候(注釋掉前兩個遞迴的方法,費時太長,比較的都是迭代的方法)

long_max:9223372036854775807

f[100]

3736710778780434371

0ms3736710778780434371

0msn:4,a:7540113804746346429,b:-6246583658587674878,cnn:46

7540113804746346429

0ms此時,迭代所用時間都在1ms之內。

自己寫的方法裡檢測到b溢位了,此時迴圈次數是46次,意味著最大支援的是2倍的92項值7540113804746346429。

3736710778780434371是已經溢位了之後,丟失了符號位得到的數值。

溢位解決,見第二章biginteger

斐波那契數列的演算法研究

背景 假定你有一雄一雌一對剛出生的兔子,它們在長到乙個月大小時開始交配,在第二月結束時,雌兔子產下另一對兔子,過了乙個月後它們也開始繁殖,如此這般持續下去。每只雌兔在開始繁殖時每月都產下一對兔子,假定沒有兔子死亡,在一年後總共會有多少對兔子?在一月底,最初的一對兔子交配,但是還只有1對兔子 在二月底...

斐波那契數列 斐波那契數列python實現

斐波那契數列 fibonacci sequence 又稱 分割數列 因數學家列昂納多 斐波那契 leonardoda fibonacci 以兔子繁殖為例子而引入,故又稱為 兔子數列 指的是這樣乙個數列 1 1 2 3 5 8 13 21 34 在數學上,斐波納契數列以如下被以遞推的方法定義 f 1 ...

迴圈斐波那契數列 斐波那契數列應用

什麼是斐波那契數列 斐波那契數列指的是這樣乙個數列 1,1,2,3,5,8,13,21,34,55,89,144 這個數列從第3項開始,每一項都等於前兩項之和 台階問題 有一段樓梯有10級台階,規定每一步只能跨一級或兩級,要登上第10級台階有幾種不同的走法?這就是乙個斐波那契數列 登上第一級台階有一...