1. 程式人生 > >求斐波那契數列的第n項值——9

求斐波那契數列的第n項值——9

    寫一個函式,輸入n,求斐波那契(Fibonacci)數列的第n項。斐波那契數列的定義如下:

         0            n = 0     

   F(n) =  1            n = 1

         F(n-1)+F(n-2)    n > 1

也就是斐波那契數列為{0,1,1,2,3,5,8,13,21,......F(n-1)+F(n-2)};

    首先可以想到,因為要求第n個斐波那契數,就需要知道第n-1和第n-2個斐波那契數,而求第n-1個斐波那契數就需要知道第n-2個和第n-3個斐波那契數,第n-2個斐波那契數就需要知道第n-3和第n-4個斐波那契數......這樣的話,可以用遞迴來實現:

#include <iostream>using namespace std;long long Fib(size_t n){    if(n < 2)        return n;    else        return Fib(n-1)+Fib(n-2);}int main(){    size_t n = 18;     long long ret = Fib(n);    cout<<"Fibonacci number of "<<n<<" is: "<<ret<<endl;    return 0;}

執行程式可得結果:

wKioL1coskzhJQzpAAAOS1wUyAA599.png

可以看到第18個斐波那契數為2584,這種情況下是沒什麼問題的,但如果將n的值再設大一點的話,比如38,或者48、58,就會發現半天運算不出來結果,這是因為遞迴會有棧的開銷,而一個稍微大點的n就會連續壓十幾個甚至好幾十個棧,這樣的話,系統的運算效率就大大降低了,因此,用遞迴來計算斐波那契數並不是最高效的解法。

    遞迴是不斷地壓棧釋放棧,在每一塊開闢出來的棧中儲存有n個斐波那契數,那麼,除了用遞迴,也可以用陣列來依次儲存從0到n個斐波那契數,用迴圈來代替棧的開銷,程式碼可如下:

long long Fib(size_t n){    if(n < 2)     //當n小於2的時候就可以直接返回效率高,就不必再開闢釋放空間了        return n;    long long *p = new long long[n+1];//因為n相當於下標,存在第0個斐波那契數,因此要開闢n+1的大小    p[0] = 0;    p[1] = 1;    for(size_t i = 2; i <= n; ++i)//迴圈控制條件下標為n的值才是要返回的值    {        p[i] = p[i-1] + p[i-2];    }    long long ret = p[n];    delete[] p;//記得釋放空間,否則會有記憶體洩露    return ret;}

執行上面的程式,會發現無論n為多大結果很快就能夠得出來,這樣的執行效率是比遞迴壓棧要高的多的;

    可是,上面的程式還是存在問題,因為如果n的值比較大的話,開闢的空間也會很大,但是我們會發現,要求第n個斐波那契數,只需要知道它前面的兩個數然後相加起來就可以了,也就是說,明明只需要三個資料的空間用來存放資料就好了卻要開闢出很大的一塊空間來將n前面所有的資料都給存放起來,因此,上面的程式雖然比遞迴壓棧效率要高,但是卻比較浪費儲存空間;上面的程式碼還是可以優化為如下的:

long long Fib(size_t n){    if(n < 2)        return n;    long long f0, f1, f2; //定義三個變數    f0 = 0;    f1 = 1;    for(size_t i = 2; i <= n; ++i)    {           f2 = f0 + f1; //每一次都用三個變數來回交換,因為要求n只需要知道前面兩個數就可以了        f0 = f1;         f1 = f2;     }       return f2; }

《完》

相關推薦

java遞迴數列n

public class Fibonacci { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int f

數列N的最後一位

RT,該怎麼求呢? 首先,你可能會想到,順序遍歷求解。 利用通項公式,可以得到斐波那契序列: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34... 那每一項的最後一位就是: 0, 1, 1, 2, 3, 5, 8, 3, 1, 4... 這樣做的效

Java練習題-數列n

/** * 求斐波那契數列第n項,n<30,斐波那契數列前10項為 1,1,2,3,5,8,13,21,34,55 * @author Tang * */ public clas

矩陣快速模冪 + 數列n(Fibonacci)

兩矩陣相乘,樸素演算法的複雜度是O(N^3)。如果求一次矩陣的M次冪,按樸素的寫法就是O(N^3*M)。既然是求冪,不免想到快速冪取模的演算法,前面有快速冪取模的介紹,a^b %m 的複雜度可以降

案例:數列n位是多少封裝函式

//斐波那契數列:1,1,2,3,5,8,13,21,34,55… //我們寫一個函式getFB()就是用來求斐波那契數列第n位的數是多少. //把已經求過的項用物件儲存起來,以後如果還要求這個項就直接取出來用,這樣就解決了效能低下的問題. funct

數列n位的幾種實現方式及效能對比(c#語言)

在每一種程式語言裡,斐波那契數列的計算方式都是一個經典的話題。它可能有很多種計算方式,例如:遞迴、迭代、數學公式。哪種演算法最容易理解,哪種演算法是效能最好的呢? 這裡給大家分享一下我對它的研究和總結:下面是幾種常見的程式碼實現方式,以及各自的優缺點、效能對比。 Iteration using Syst

數列Nf(N)[矩陣快速冪]

string sin int code char const mat ret truct 矩陣快速冪   定義矩陣A(m*n),B(p*q),A*B有意義當且僅當n=p。即A的列數等於B的行數。   且C=A*B,C(m*q)。   例如:   進入正題,由於現

數列n

Description 輸入n,求斐波那契數列前n項的值。斐波那契數列規律如下:1, 1, 2, 3, 5, 8, 13,21, 34,55…,從第三項開始,每一項都是前面兩項的和。 Input 輸入正整數n。 Output 輸出斐波那契數列的前n項值 Sample Input

使用線性代數求解數列n

一:問題 已知斐波那契數列,f1=1,f2=1,f3=3,f4=5...求第n項的數值 二:問題轉化為線性代數問題 可以得到方程 f(n+2)=f(n+1)+f(n) 為了解決問題,新增方程 f(n+1)=f(n+1) 記向量,則上兩式可以寫作 要求,只需知道,

數列N的3個寫法(JS)

 題目: 求斐波拉切數列第n個數的值是多少? 數列:1,1,2,3,5,8,13,21...... 第一種,for迴圈,直接求N項 // i代表第三項,res代表第i項的時候的值,通過前面2項相加去實現,n項的時候跳出迴圈,輸出res function fb(n){ v

數列n的三種求法

方法1:         利用遞迴方法,但是遞迴看似簡單但是無法處理較大的項數,時間複雜度為o(2^n)。 public class fib_遞迴 { /** * @param args */ public static

數列N(C++)

求斐波那契數的第N項,N可以很大但結果不能超過1000位; #include <iostream> #include <memory.h> #include <strin

遞迴用python求解數列n

      波那契數列(Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的

求解數列n(JavaBigInteger之自底向上迭代)

import java.math.BigInteger; import java.util.*; public class Fab //用迭代法自底向上求解斐波那契數列第n項 { publi

數列N

#include<stdio.h> int FibonacciSequence(int n) { int f1=1; int f2=1; int f3=1; for(int i=3;i<=n;i++) { f3=f1+f2; f1=f2;

數列n的高效解法

參考書籍《劍指Offer》 常見解法 談及斐波那契數列,我們直接就可以想到f(n)=f(n-1)+f(n-2)。於是做出如下解: long long Fibonacci(unsigned

隨機數列n位的代碼

-- Go golden tint lse [] next util ret 1------------------------------------------------------------ package oo.day02;import java.util.Sc

藍橋杯——數列n個取餘10007的結果

藍橋杯要求的輸入和輸出一定要一模一樣,不需要多餘的輸入或者輸出!#include<stdio.h>int main(){int F[1000000] = {1,1};int n,i,m;scanf("%d",&n);for(i = 2;i < n;i

【C++】數列N的和遞迴與非遞迴演算法

定義:斐波那契數列(Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是這樣一個數列:0、1、1、2、3、5、8、1

【Java】數列N(堆疊演算法)

堆疊是一種很靈活的"後進先出"資料結構,使用堆疊可以節省記憶體的開銷。比如,遞迴是一種很消耗記憶體的演算法,可以藉助堆疊消除大部分遞迴,達到和遞迴演算法同樣的目的。 下面用例子實現求斐波那契數列前N項