1. 程式人生 > >斐波那契數列介紹及Python中五種方法斐波那契數列

斐波那契數列介紹及Python中五種方法斐波那契數列

Q:斐波那契數列為什麼那麼重要,所有關於數學的書幾乎都會提到?
A:因為斐波那契數列在數學和生活以及自然界中都非常有用。

在這裡插入圖片描述

1. 斐波那契數列 概念引入

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

數學上,斐波那契數列以遞迴的形式進行定義:
F 0

= 0 F 1 = 1 F n
= F n 1 + F
n 2
F_{0} = 0\\ F_{1} = 1\\ F_{n} = F_{n-1} + F_{n-2}

場景

先來開看看“兔子數列”以及其他數學應用場景!!

1. 1 兔子數列

一般而言,兔子在出生兩個月後,就有繁殖能力,一對兔子每個月能生出一對小兔子來。如果所有兔子都不死,那麼一年以後可以繁殖多少對兔子?

在這裡插入圖片描述

1.2 排列組合

有一段樓梯有10級臺階,規定每一步只能跨一級或兩級,要登上第10級臺階有幾種不同的走法?

更多數學方面知識,請戳:
斐波那契數列

斐波那契數列為什麼那麼重要,所有關於數學的書幾乎都會提到?

2. 數列數學方法解答

2.1 兔子繁殖問題

斐波那契數列又因數學家列昂納多·斐波那契以兔子繁殖為例子而引入,故又稱為“兔子數列”。

一般而言,兔子在出生兩個月後,就有繁殖能力,一對兔子每個月能生出一對小兔子來。如果所有兔子都不死,那麼一年以後可以繁殖多少對兔子?

我們不妨拿新出生的一對小兔子分析一下:

第一個月小兔子沒有繁殖能力,所以還是一對

兩個月後,生下一對小兔對數共有兩對

三個月以後,老兔子又生下一對,因為小兔子還沒有繁殖能力,所以一共是三對

------

依次類推可以列出下表:

經過月數 1 2 3 4 5 6 7 8 9 10 11 12
幼仔對數 1 0 1 1 2 3 5 8 13 21 34 55
成兔對數 0 1 1 2 3 5 8 13 21 34 55 89
總體對數 1 1 2 3 5 8 13 21 34 55 89 144

幼仔對數=前月成兔對數

成兔對數=前月成兔對數+前月幼仔對數

總體對數=本月成兔對數+本月幼仔對數

可以看出幼仔對數、成兔對數、總體對數都構成了一個數列。這個數列有關十分明顯的特點,那是:

前面相鄰兩項之和,構成了後一項。

2.2 排列組合
2.2.1 跨樓梯組合

有一段樓梯有10級臺階,規定每一步只能跨一級或兩級,要登上第10級臺階有幾種不同的走法?

這就是一個斐波那契數列:登上第一級臺階有一種登法;登上兩級臺階,有兩種登法;登上三級臺階,有三種登法;登上四級臺階,有五種登法……

1,2,3,5,8,13……所以,登上十級,有89種走法。

2.2.2 擲硬幣不連續情形

一枚均勻的硬幣擲10次,問不連續出現正面的可能情形有多少種?

答案是:
1 / 5 ) [ ( 1 + 5 ) / 2 ] ( 10 + 2 ) [ ( 1 5 ) / 2 ] ( 10 + 2 ) = 144 (1/√5)*{[(1+√5)/2]^(10+2) - [(1-√5)/2]^(10+2)}=144

3. Python程式碼實現斐波那契數列

時間複雜度

空間複雜度

通過時間複雜度空間複雜度評判程式碼的執行效率。

  • 例如:從規模上來說,如果需要計算F(4)的值,需要進行9次元素操作

    設T(n)為計算n的時間複雜度,那麼
    T ( n ) = T ( n 1 ) + T ( n 2 ) + O ( 1 ) T(n) = T(n-1) + T(n-2)+O(1)
    一般情況,可以得出: T ( n ) < 2 T ( n 1 ) + O ( 1 ) T(n)< 2* T(n-1) + O(1)

    粗略估算, T n < O 2 n T(n) < O(2^n) ,上述程式碼求解F(n)的計算,它的時間複雜度是$O(2^n)

3.1 python特有寫法

列印正整數n之內的斐波那契數列

# Python特有, 常規寫法
def fib(self, n):
	a = 0
	b = 1
	while a <= n:
		print(a, end=" ", flush=True)
		a, b = b, a + b  # python不借助變數交換兩數的值

fib(100)  # 求n之內的斐波那契數列

O ( n ) O ( 1 ) 時間複雜度:O(n), 空間複雜度:O(1)

3.2 遞迴

列印斐波那契數列前10位數字

# 遞迴
def fibonacci(i):
    num_list = [0, 1]
    if i < 2:
        return num_list[i]
    elif i >= 2:
        return (fibonacci(i - 2) + fibonacci(i - 1))


print(fibonacci(10))

O ( n ) O ( n ) 時間複雜度:O(n), 空間複雜度:O(n)

3.3 類物件
# 迭代的方式
class FibIterator(object):
    """斐波那契數列迭代器"""
    def __init__(self, n):
        """
        :param n: int, 指明生成數列的前n個數
        """
        self.n = n
        # current用來儲存當前生成到數列中的第幾個數了
        self.current = 0
        # num1用來儲存前前一個數,初始值為數列中的第一個數0
        self.num1 = 0
        # num2用來儲存前一個數,初始值為數列中的第二個數1
        self.num2 = 1

    def __next__(self):
        """被next()函式呼叫來獲取下一個數"""
        if self.current < self.n:
            num = self.num1
            self.num1, self.num2 = self.num2, self.num1+self.num2
            self.current += 1
            return num
        else:
            raise StopIteration

    def __iter__(self):
        """迭代器的__iter__返回自身即可"""
        return self


if __name__ == '__main__':
    fib = FibIterator(10)
    for num in fib:
        print(num, end=" ")
3.4 矩陣解決問題

從定義開始:
F 0 = 0 F 1 = 1 F n = F n 1 + F n 2 F_{0} = 0\\ F_{1} = 1\\ F_{n} = F_{n-1} + F_{n-2}
轉化為矩陣形式
( F n + 1 F n ) = ( 1 1 1 0 ) ( F n F n 1 ) \begin{pmatrix} F_{n+1}\\ F_{n} \end{pmatrix}= \begin{pmatrix} 1&amp;1\\ 1&amp;0 \end{pmatrix}* \begin{pmatrix} F_{n}\\ F_{n-1} \end{pmatrix}
可以得出: ( F n + 1 F n ) ( 1 1 1 0 ) ( F 1 F 0 ) \begin{pmatrix} F_{n+1}\\ F_{n} \end{pmatrix}\begin{pmatrix} 1&amp;1\\ 1&amp;0 \end{pmatrix}\begin{pmatrix} F_{1}\\ F_{0} \end{pmatrix}
我們設定
A = ( 1 1 <