最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

一、遞歸

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

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);
}

    如果計(jì)算數(shù)列的第4個(gè)位置上(從0開(kāi)始)的數(shù)(0 1 1 2 3),也就是3,上邊的 printf 輸出應(yīng)該是 4 3 2 1 0 1 2 1 0,這是因?yàn)橛?jì)算 F(4) 要計(jì)算 F(3) 和 F(2),而計(jì)算 F(3) 的時(shí)候又要計(jì)算 F(2) 和 F(1),所以會(huì)有很多重復(fù)計(jì)算。用下圖可以更好地說(shuō)明。

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

    而且除了效率問(wèn)題之外,遞歸可能引起 調(diào)用棧溢出,因?yàn)樾枰獮槊恳淮魏瘮?shù)調(diào)用在內(nèi)存棧中分配空間,而每個(gè)進(jìn)程的棧的容量是有限的。當(dāng)?shù)俟痰膶蛹?jí)太多,就會(huì)超出棧的容量,導(dǎo)致棧溢出。比如上邊的代碼,輸入40,可以正確返回 12502500,但是輸入 5000 就會(huì)出錯(cuò)。

二、循環(huán)

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

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í)間復(fù)雜度的算法,就是利用數(shù)學(xué)公式計(jì)算。

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

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

     所以我們可以看出,想求 n 次方可以求出 n / 2 次方再平方,所以時(shí)間復(fù)雜度可以將為 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;
}

    為了測(cè)試上邊三種方式的代碼的正確性,可以用如下樣例來(lái)測(cè)試。

// ====================測(cè)試代碼====================
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;
}

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

相關(guān)文章

  • C++中vector的模擬實(shí)現(xiàn)實(shí)例詳解

    C++中vector的模擬實(shí)現(xiàn)實(shí)例詳解

    vector是表示可變大小數(shù)組的序列容器,它也采用連續(xù)存儲(chǔ)空間來(lái)存儲(chǔ)元素,因此可以采用下標(biāo)對(duì)vector的元素進(jìn)行訪問(wèn),這篇文章主要給大家介紹了關(guān)于C++中vector模擬實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • 深入理解C++中常見(jiàn)的關(guān)鍵字含義

    深入理解C++中常見(jiàn)的關(guān)鍵字含義

    本篇文章是對(duì)C++中常見(jiàn)關(guān)鍵字的含義進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++實(shí)現(xiàn)Window環(huán)境聊天室功能

    C++實(shí)現(xiàn)Window環(huán)境聊天室功能

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)Window環(huán)境聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • 簡(jiǎn)單比較C語(yǔ)言中的execl()函數(shù)與execlp()函數(shù)

    簡(jiǎn)單比較C語(yǔ)言中的execl()函數(shù)與execlp()函數(shù)

    這篇文章主要介紹了C語(yǔ)言中的execl()函數(shù)與execlp()函數(shù)的簡(jiǎn)單比較,是C語(yǔ)言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-08-08
  • c語(yǔ)言中static的用法詳細(xì)示例分析

    c語(yǔ)言中static的用法詳細(xì)示例分析

    以下是對(duì)c語(yǔ)言中static函數(shù)的用法進(jìn)行了詳細(xì)的分析介紹,需要的朋友可以過(guò)來(lái)參考下
    2013-08-08
  • 基于C語(yǔ)言實(shí)現(xiàn)學(xué)生管理系統(tǒng)

    基于C語(yǔ)言實(shí)現(xiàn)學(xué)生管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了基于C語(yǔ)言實(shí)現(xiàn)學(xué)生管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C語(yǔ)言快速掌握位段使用

    C語(yǔ)言快速掌握位段使用

    位段位段的聲明和結(jié)構(gòu)是類似的,但是也會(huì)有所不同,此篇文章將帶你了解位段是什么已以及位段的使用和位段的特性,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2022-09-09
  • 基于C++實(shí)現(xiàn)TCP聊天室功能

    基于C++實(shí)現(xiàn)TCP聊天室功能

    這篇文章主要為大家詳細(xì)介紹了基于C++實(shí)現(xiàn)TCP聊天室功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C語(yǔ)言中g(shù)etopt()函數(shù)和select()函數(shù)的使用方法

    C語(yǔ)言中g(shù)etopt()函數(shù)和select()函數(shù)的使用方法

    這篇文章主要介紹了C語(yǔ)言中g(shù)etopt()函數(shù)和select()函數(shù)的使用方法,是C語(yǔ)言入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-09-09
  • C 語(yǔ)言環(huán)境設(shè)置詳細(xì)講解

    C 語(yǔ)言環(huán)境設(shè)置詳細(xì)講解

    本文主要介紹C 語(yǔ)言環(huán)境設(shè)置,在不同的系統(tǒng)平臺(tái)上,C語(yǔ)言的環(huán)境設(shè)置不同,這里幫大家整理了Liunx, UNIX,Windows 上安裝C語(yǔ)言環(huán)境,有開(kāi)始學(xué)習(xí)C語(yǔ)言的朋友可以參考下
    2016-08-08

最新評(píng)論

龙胜| 县级市| 牡丹江市| 昌乐县| 长岛县| 镇巴县| 驻马店市| 登封市| 邵阳市| 陆丰市| 康平县| 盐源县| 武定县| 米脂县| 米林县| 抚松县| 瓦房店市| 塘沽区| 安塞县| 博乐市| 额敏县| 玉门市| 开阳县| 蓬莱市| 文安县| 中江县| 阿城市| 台南市| 宜昌市| 霍林郭勒市| 荃湾区| 西安市| 建瓯市| 都匀市| 乌拉特后旗| 鄂温| 宜宾市| 淮阳县| 鲜城| 华容县| 琼海市|