亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

C語言中斐波那契數(shù)列的三種實現(xiàn)方式(遞歸、循環(huán)、矩陣)

 更新時間:2022年01月24日 11:31:16   作者:Bob__yuan  
本文主要介紹了C語言中斐波那契數(shù)列的三種實現(xiàn)方式(遞歸、循環(huán)、矩陣),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

《劍指offer》里講到了一種斐波那契數(shù)列的 O(logN) 時間復雜度的實現(xiàn),覺得挺有意思的,三種方法都記錄一下。

一、遞歸

    一般來說遞歸實現(xiàn)的代碼都要比循環(huán)要簡潔,但是效率不高,比如遞歸計算斐波那契數(shù)列第n個元素。

long long Fibonacci_Solution1(unsigned int n) {
    // printf("%d ", n);
    if (n <= 0) return 0;
    if (n == 1) return 1;
    return Fibonacci_Solution1(n - 1) + Fibonacci_Solution1(n - 2);
}

    如果計算數(shù)列的第4個位置上(從0開始)的數(shù)(0 1 1 2 3),也就是3,上邊的 printf 輸出應該是 4 3 2 1 0 1 2 1 0,這是因為計算 F(4) 要計算 F(3) 和 F(2),而計算 F(3) 的時候又要計算 F(2) 和 F(1),所以會有很多重復計算。用下圖可以更好地說明。

    遞歸雖然有簡潔的優(yōu)點,但它同時也有顯著地缺點。遞歸由于是函數(shù)調用自身,而函數(shù)調用是有空間和時間的消耗的:每一次函數(shù)調用,都需要在內存棧中分配空間以保存參數(shù)、返回地址及臨時變量,而且往棧里壓入數(shù)據和彈出數(shù)據都需要時間。

    而且除了效率問題之外,遞歸可能引起 調用棧溢出,因為需要為每一次函數(shù)調用在內存棧中分配空間,而每個進程的棧的容量是有限的。當?shù)俟痰膶蛹壧?,就會超出棧的容量,導致棧溢出。比如上邊的代碼,輸入40,可以正確返回 12502500,但是輸入 5000 就會出錯。

二、循環(huán)

    最常規(guī)的正確做法就是用循環(huán)從小到大計算。

long long Fibonacci_Solution2(unsigned n) {
    if (n <= 1) return n;
    long long  fib1 = 1, fib0 = 0, fibN = 0;
    for (unsigned int i = 2; i <= n; ++i) {
        fibN = fib1 + fib0;
        fib0 = fib1;
        fib1 = fibN;
    }
    return fibN;
}

    或者下邊這種

long long Fibonacci_Solution2(unsigned n) {
    if (n <= 1) return n;
    long long a = 0, b = 1;
    for (unsigned int i = 2; i <= n; ++i) {
        b = a + b;
        a = b - a;
    }
    return b;
}

三、矩陣

    數(shù)中提到了一種 O(logN) 時間復雜度的算法,就是利用數(shù)學公式計算。

    首先需要知道下邊這個數(shù)學公式:

     這個公式用數(shù)學歸納法可以證明,所以只需要計算右邊矩陣的 n-1 次方就能得到 f(n),現(xiàn)在問題就變成了計算 2x2 矩陣的 n-1 次方,這樣做 n-2 次乘法就可以了,時間復雜度還是 O(N),但是還可以加速,如下式:

     所以我們可以看出,想求 n 次方可以求出 n / 2 次方再平方,所以時間復雜度可以將為 O(logN)。

struct Matrix2By2 {
    Matrix2By2(long long m00 = 0, long long m01 = 0, long long m10 = 0,	long long m11 = 0)
        :m_00(m00), m_01(m01), m_10(m10), m_11(m11) {}
    long long m_00, m_01, m_10, m_11;
};
 
Matrix2By2 MatrixMultiply(const Matrix2By2& matrix1, const Matrix2By2& matrix2) {
    return Matrix2By2(  matrix1.m_00 * matrix2.m_00 + matrix1.m_01 * matrix2.m_10,
                        matrix1.m_00 * matrix2.m_01 + matrix1.m_01 * matrix2.m_11,
                        matrix1.m_10 * matrix2.m_00 + matrix1.m_11 * matrix2.m_10,
                        matrix1.m_10 * matrix2.m_01 + matrix1.m_11 * matrix2.m_11    );
}
 
Matrix2By2 MatrixPower(unsigned int n) {
    assert(n > 0);
    Matrix2By2 matrix;
    if (n == 1)
        matrix = Matrix2By2(1, 1, 1, 0);
    else if (n % 2 == 0) {	// n是偶數(shù)
        matrix = MatrixPower(n / 2);
        matrix = MatrixMultiply(matrix, matrix);
    }
    else if (n % 2 == 1) {	// n是奇數(shù)
        matrix = MatrixPower((n - 1) / 2);
        matrix = MatrixMultiply(matrix, matrix);
        matrix = MatrixMultiply(matrix, Matrix2By2(1, 1, 1, 0));
    }
    return matrix;
}
 
long long Fibonacci_Solution3(unsigned int n) {
    if (n <= 1) return n;
    Matrix2By2 PowerNMinus2 = MatrixPower(n - 1);
    return PowerNMinus2.m_00;
}

    為了測試上邊三種方式的代碼的正確性,可以用如下樣例來測試。

// ====================測試代碼====================
void Test(int n, int expected) {
    if (Fibonacci_Solution1(n) == expected)
        printf("Test for %d in solution1 passed.\n", n);
    else
        printf("Test for %d in solution1 failed.\n", n);
 
    if (Fibonacci_Solution2(n) == expected)
        printf("Test for %d in solution2 passed.\n", n);
    else
        printf("Test for %d in solution2 failed.\n", n);
 
    if (Fibonacci_Solution3(n) == expected)
        printf("Test for %d in solution3 passed.\n", n);
    else
        printf("Test for %d in solution3 failed.\n", n);
}
 
int main(int argc, char* argv[]) {
    Test(0, 0);
    Test(1, 1);
    Test(2, 1);
    Test(3, 2);
    Test(4, 3);
    Test(5, 5);
    Test(6, 8);
    Test(7, 13);
    Test(8, 21);
    Test(9, 34);
    Test(10, 55);
    Test(40, 102334155);
    return 0;
}

到此這篇關于C語言中斐波那契數(shù)列的三種實現(xiàn)方式(遞歸、循環(huán)、矩陣)的文章就介紹到這了,更多相關C語言 斐波那契數(shù)列內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C++實現(xiàn)設計模式之裝飾者模式詳解

    C++實現(xiàn)設計模式之裝飾者模式詳解

    這篇文章主要介紹了C++設計模式之裝飾模式,裝飾模式能夠實現(xiàn)動態(tài)的為對象添加功能,是從一個對象外部來給對象添加功能,需要的朋友可以參考下
    2021-09-09
  • C語言編程之初識數(shù)組線性查找和二分查找

    C語言編程之初識數(shù)組線性查找和二分查找

    本篇文章是C語言編程篇,主要為大家介紹C語言編程中數(shù)組的線性查找及二分查找分析講解,有需要的朋友可以借鑒參考下,希望可以有所幫助
    2021-09-09
  • C++學習之初始化列表詳解

    C++學習之初始化列表詳解

    這篇文章主要為大家詳細介紹了C++中初始化列表的相關知識,文中的示例代碼講解詳細,對我們學習C++有一定的幫助,需要的小伙伴可以了解一下
    2023-03-03
  • C語言中的getchar()使用詳解

    C語言中的getchar()使用詳解

    大家好,本篇文章主要講的是C語言中的getchar()使用詳解,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • C/C++?Qt?TableDelegate?自定義代理組件使用詳解

    C/C++?Qt?TableDelegate?自定義代理組件使用詳解

    TableDelegate自定義代理組件的主要作用是對原有表格進行調整,本文主要介紹了QT中TableDelegate?自定義代理組件的使用教程,感興趣的朋友可以了解一下
    2021-12-12
  • C++鏈表類的封裝詳情介紹

    C++鏈表類的封裝詳情介紹

    這篇文章主要介紹了C++鏈表類的封裝,文章基于C++的相關資料展開主題的詳細內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-04-04
  • C語言實現(xiàn)按月顯示的日歷

    C語言實現(xiàn)按月顯示的日歷

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)按月顯示的日歷,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • C++ GDI實現(xiàn)圖片格式轉換

    C++ GDI實現(xiàn)圖片格式轉換

    GDI+(Graphics Device Interface Plus)是一種用于圖形繪制和圖像處理的應用程序編程接口(API),在Windows平臺上廣泛使用,本文就來介紹一下如何使用GDI實現(xiàn)圖片格式轉換吧
    2023-12-12
  • C/C++使用Zlib實現(xiàn)文件的壓縮與解壓

    C/C++使用Zlib實現(xiàn)文件的壓縮與解壓

    zlib 是一個開源的數(shù)據壓縮庫,旨在提供高效、輕量級的壓縮和解壓縮算法,本文將介紹如何使用 zlib 庫進行數(shù)據的壓縮和解壓縮,以及如何保存和讀取壓縮后的文件,感興趣的可以了解下
    2023-11-11
  • C語言實現(xiàn)簡單的三子棋游戲

    C語言實現(xiàn)簡單的三子棋游戲

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)三子棋游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-09-09

最新評論