首頁技術文章正文

探秘斐波拉契數(shù)列!

更新時間:2022-11-16 來源:黑馬程序員 瀏覽量:

  介紹

   斐波那契數(shù)列(Fibonacci sequence),又稱黃金分割數(shù)列,因數(shù)學家萊昂納多·斐波那契(Leonardo Fibonacci)以兔子繁殖為例子而引入,故又稱為“兔子數(shù)列”,指的是這樣一個數(shù)列:1、1、2、3、5、8、13、21、34、……在數(shù)學上,斐波那契數(shù)列以如下被以遞推的方法定義:*F*(0)=0,*F*(1)=1, *F*(n)=*F*(n - 1)+*F*(n - 2)(*n* ≥ 2,*n* ∈ N*)在現(xiàn)代物理、晶體結(jié)構(gòu)、化學等領域,斐波納契數(shù)列都有直接的應用,為此,美國數(shù)學會從 1963 年起出版了以《斐波納契數(shù)列季刊》為名的一份數(shù)學雜志,用于專門刊載這方面的研究成果。

  java中如何編碼實現(xiàn)斐波那契數(shù)列

  方案1:遞歸

   根據(jù)斐波那契數(shù)列的數(shù)學表示方式:*F*(1)=1,*F*(2)=1, *F*(n)=*F*(n - 1)+*F*(n - 2)(*n* ≥ 2,*n* ∈ N*)

   很容易就可以得出:

public int fib(int n) {
    if(n <= 2) return 1;
    return fib(n - 1) + fib(n - 2);
}

  問題:使用以上代碼完成斐波那契數(shù)列,時間復雜度是0(n^2),空間復雜度是0(n);

   我們以fib(6)為例: 時間復雜度很明顯是0(n^2)

1668571139691_2.jpg

  空間復雜度是0(n)

1668571153953_3.jpg

  方案2: 基于數(shù)組進行優(yōu)化

   方案1中很多的代碼,存在重復調(diào)用.可以考慮使用一個數(shù)組存放,之前調(diào)用得到的結(jié)果;

  public int fib(int n) {
        if(n <= 2) return 1;
        int[] array = new int[n + 1]; //定義數(shù)組,存放已經(jīng)得到結(jié)果的數(shù)據(jù)
        array[1] = array[2] = 1;
        return fib(n,array);
    }

    public int fib(int n,int[] array) {
        if(array[n] == 0) { //判斷數(shù)組中是否有元素,如果有,直接返回,沒有,遞歸。
            array[n] = fib(n -1 ,array) + fib(n - 2,array);
        }
        return array[n];
    }

  問題:使用以上代碼完成斐波那契數(shù)列,時間復雜度是0(n),空間復雜度是0(n);

   空間復雜度:額外定義了一個數(shù)組;空間復雜度依然是0(n)。

   時間復雜度:由于沒有了重復的調(diào)用,時間復雜度是0(n)。

  方案3: 將遞歸轉(zhuǎn)化為非遞歸優(yōu)化

   定義一個數(shù)組存放,存放斐波拉契數(shù)列每一項數(shù)據(jù);免去遞歸調(diào)用;

  public int fib(int n) {
        if(n <= 2) return 1;
        int[] array = new int[n + 1];
        array[1] = array[2] = 1;
        for (int i = 3; i <= n; i++) {
            array[i] = array[i - 1] + array[i - 2];
        }
        return array[n];
 }

  空間復雜度:額外定義了一個數(shù)組;空間復雜度依然是0(n),但是沒有遞歸產(chǎn)生的空間。

   時間復雜度:時間復雜度是0(n)

  方案4: 滾動數(shù)組降低空間復雜度;

   對于斐波拉契數(shù)列,只需要2個數(shù)組空間即可;

 public int fib(int n) {
        if(n <= 2) return 1;
        int[] array = new int[2];
        array[0] = array[1] = 1;
        for (int i = 3; i <= n ; i++) {
            array[(i - 1) & 1] = array[(i - 1)  & 1] + array[(i - 2) & 1];
        }
        return array[( n - 1)  & 1];
    }

  空間復雜度:額外定義了一個數(shù)組;但是長度只有2,所以空間復雜度0(1);

   時間復雜度:時間復雜度是0(n)

  方案5:定義2個變量代替數(shù)組

 public int fab5(int n) {
        if(n <= 2) return 1;
        int n1 = 1;
        int n2 = 1;
        for (int i=3;i<=n;i++) {
            n2 = n1 + n2;
            n1 = n2 - n1;
        }
        return n2;
 }

  空間復雜度:不需要額外定義數(shù)組,只定義2個變量即可,所以空間復雜度0(1);

  時間復雜度:時間復雜度是0(n)

  方案6:使用線性方程;

1668570998095_1.jpg

  方案7:利用尾遞歸實現(xiàn),java可以對尾遞歸的??臻g優(yōu)化

    public int fab7(int n) {
       return fab7(n,1,1);
    }

    public int fab7(int n, int n1,int n2) {
        if(n <= 2) {
            return n2;
        }
        return fab7(n - 1,n2,n1+n2);
    }

  空間復雜度:遞歸的深度為0(n),但是由于是尾遞歸,優(yōu)化后的空間復雜度是0(1)

  時間復雜度:時間復雜度是0(n)

分享到:
在線咨詢 我要報名
和我們在線交談!