【剑指offer - C++/Java】7、斐波那契数列
在線題目鏈接:斐波那契數列
文章目錄
- 1、題目描述
- 2、題目分析
- 3、代碼
- 3.1 遞歸方法
- 3.11 Java代碼
- 3.12 C++代碼
- 3.2 動態規劃
- 3.21 Java代碼
- 3.22 C++代碼
- 3.3 循環方法
- 3.31 Java代碼
- 3.32 C++代碼
- 4、總結
1、題目描述
大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項為0)。
n<=39
2、題目分析
有高中的數學知識,就應該知道斐波那契數列是這樣的:1,1,2,3,5,8…
如果f(n)代表斐波那契數列第n項的值,那么:
既然我們已經可以得出公式了,那就很好寫代碼。最容易明白的就是遞歸了,上面的公式其實就是一個遞歸的公式。
下面提供多種解法:遞歸,動態規劃,循環。
3、代碼
3.1 遞歸方法
遞歸解法很簡單:
3.11 Java代碼
public class Solution {public int Fibonacci(int n) {//遞歸解法if(n<=1)return n;return Fibonacci(n-1)+Fibonacci(n-2);} }3.12 C++代碼
class Solution { public:int Fibonacci(int n) {//遞歸解法,超時if(n<=1)return n;return Fibonacci(n-1)+Fibonacci(n-2);} };我們都知道這種遞歸解法會有很多重復的計算,就像下面的,假設我們要計算f(10):
計算f(10),要重復計算兩次f(8),三次f(7),三次f(6),這種重復計算,對于數據比較大的時候,開銷是非常大的。所以我們經常說,遞歸雖然好寫,但是不建議在實現算法的時候使用遞歸算法。
3.2 動態規劃
凡是能用遞歸寫出的代碼,一定能夠用動態規劃寫出來。
我們知道遞歸是為了求某一個值,而必須先知道另外的幾個值后才能求出來。而想要求那另外的幾個值,還需要再求另外的另外的值,就像上面的遞歸二叉樹,想要先求f(10),必須知道f(9)和f(8)。想要知道f(9)又得知道f(8)和f(7)…
上面遞歸是想要計算總體值,需要求局部的值,想要求局部的值,又要求局部的局部的值。
動態規劃不是這樣,動態規劃是先從遞歸的終止條件開始計算,也就是說,動態規劃先計算局部的值,然后根據局部的值的累積,最終得到整體要求的值。也就是與遞歸反過來了。
比如針對上面的求f(10),我們先求f(1),f(2),f(3)…最終肯定會求得f(10)。這樣我們就沒有進行重復的計算。每一項都是只計算一次。
看代碼就能明白上面說的是什么意思了。下面的ret數組,ret[i]代表斐波那契數組的第i項。我們要求得第n項,最后求到ret[n]直接返回即可。
3.21 Java代碼
public class Solution {public int Fibonacci(int n) {//動態規劃if(n<=1)return n;int[] ret=new int[n+1];ret[0]=0;ret[1]=1;int i;for(i=2;i<=n;i++){ret[i]=ret[i-1]+ret[i-2];}return ret[n];} }3.22 C++代碼
class Solution { public:int Fibonacci(int n) {//動態規劃//if(n<=1)return n;不知道這里為什么不能加這個int ret[n+1];ret[0]=0;ret[1]=1;int i;for(i=2;i<=n;i++){ret[i]=ret[i-1]+ret[i-2];}return ret[n];} };3.3 循環方法
所有的遞歸都可以寫成動態規劃,同理所有的動態規劃,也一定能寫成循環。只不過有的動態規劃不好寫成循環而已。本題是非常好寫成循環的。
循環比動態規劃好的原因在于,循環只用幾個變量,循環使用它們得到最終結果,不保存之前的計算結果,動態規劃卻需要開辟一個數組,將所有計算過的結果保存,這很浪費空間。
3.31 Java代碼
public class Solution {public int Fibonacci(int n) {//循環if(n<=1)return n;int ret=0;int r0=0,r1=1;int i;for(i=2;i<=n;i++){ret=r0+r1;r0=r1;r1=ret;}return ret;} }當然,上面使用三個變量,我們還可以再減少一個變量,使用兩個變量:
public class Solution {public int Fibonacci(int n) {if(n<=1)return n;int r1=0,r2=1,i;for(i=2;i<=n;i++){r2+=r1;r1=r2-r1;}return r2;} }3.32 C++代碼
三個變量
class Solution { public:int Fibonacci(int n) {//循環if(n<=1)return n;int ret=0;int r0=0,r1=1;int i;for(i=2;i<=n;i++){ret=r0+r1;r0=r1;r1=ret;}return ret;} };兩個變量
class Solution { public:int Fibonacci(int n) {if(n<=1)return n;int r1 = 0, r2 = 1,i;for(i=2;i<=n;i++){r2+=r1;r1=r2-r1;}return r2;} };4、總結
注意學會遞歸,動態規劃,循環三者時間的關系
探討學習加:
個人qq:1126137994
個人微信:liu1126137994
總結
以上是生活随笔為你收集整理的【剑指offer - C++/Java】7、斐波那契数列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 已解决:如何使用IDEA生成java帮助
- 下一篇: s3c2440移植MQTT