python定义函数计算斐波那契公式前20的项_Python3算法之二:斐波那契函数
關注微信公眾號“酸痛魚”,獲得更多最新最全的文章。
本文中所涉及的代碼,在未特殊聲明的情況下,都是基于Python3程序設計語言編寫的。
建議您在PC瀏覽器中閱讀本文,以獲得更好的閱讀體驗。
如果您未掌握知識提要中的內容,建議您先掌握這些內容之后再閱讀本文。
知識提要
1、斐波那契函數
2、函數的定義、遞歸
3、時間復雜度、空間復雜度
4、作用域、關鍵字global
0
什么是斐波那契函數
斐波那契數列,是指這樣一個數列:
1、1、2、3、5、8、13、21、24、55……
其特點是,n>=3時,第n項的值為第n-2項和第n-1項的和。我們用f(n)表式其遞推公式,即第n項的值,則:
f(n) = f(n-2) + f(n-1) ; n>=3, f(1)=1, f(2)=1
我們將這個遞推公式稱為斐波那契函數。
1
遞歸方式實現斐波那契函數
斐波那契函數的定義是遞歸定義,我們很容易想到遞歸的方式。話不多說,我們直接看代碼。
def fib(n):
# 遞歸結束條件
# 為了處理方便,n <= 0 時,直接返回 1
if n <= 2:
return 1
return fib(n - 1) + fib(n - 2)
沒錯,四行代碼,我們就實現了一個算法題目。但這個代碼的效率是非常低的。
使用遞歸的方式,會出現很多重復的運算。例如,當我們計算fib(5)的時候,會遞歸調用fib(4)和fib(3),其中fib(4)又會重復計fib(3)。
事實上,這種實現方式的時間復雜度O(2^n),空間復雜度為O(n)。
巧合的是,對于一次fib(n)調用,假設其實返回值為An,函數fib被遞歸調用的次數為2 * An - 1。我們可以寫個代碼驗證一下。至于為什么有這個巧合,感興趣的讀者可以運用數學的方式推算一下。
calls = 0 # 全局變量,用于記錄fib被調用的次數
def fib(n):
global calls # 聲明使用全局的calls,而非重新創建局部的變量
calls += 1
if n <= 2: return 1
return fib(n - 1) + fib(n - 2)
def test(n):
global calls
calls = 0
an = fib(n)
print("n:{}, fib(n):{}, calls:{}".format(n, an, calls))
if __name__ == "__main__":
test(1)
test(2)
test(3)
test(10)
test(20)
test(30)
以上代碼的運行結果如下:
n:1, fib(n):1, calls:1
n:2, fib(n):1, calls:1
n:3, fib(n):2, calls:3
n:10, fib(n):55, calls:109
n:20, fib(n):6765, calls:13529
n:30, fib(n):832040, calls:1664079
2
線性方式實現斐波那契函數
斐波那契數列的特點是,第N項的值為第N-1項和第N-2項的和。同理,N+1項的值為第N項和N-1項的和。
所以,在程序實在的層面上,我們可以通過不停的記錄N和第N-1,來求得新最新的第N項的和。通過這種方式,我們可以時間復雜O(n)的方式實現斐波那契函數,同時,其實空間復雜度也僅為O(1)。
def fib(n):
an_1 = 1 # 第n-1項
an = 1 # 第n項 (初始為第2項)
# 至少從第3輪才循環迭代
i = 3
while i <= n:
i += 1
# 左邊為最新值,右邊為上一輪的值
an_1, an = an, an + an_1
return an
3
通項公式
斐波那契數列的通項公式為:
理論上,根據通項公式實現斐波那契函數,時間復雜度為O(1)。但事實上,如果我們按照這個公式去寫代碼,并不能得到正確的解。這是因為計算在處理浮點數的時候,并不總能保證其實精度。
計算機領域,有一個學科叫《科學計算》,就涉及到浮點數精密計算的問題,感興趣的讀者可以去了解一下。微信掃碼關注我嗄嘎嘎
酸痛魚,與你分享快樂的代碼
總結
以上是生活随笔為你收集整理的python定义函数计算斐波那契公式前20的项_Python3算法之二:斐波那契函数的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: python替换缺失值_详解Pandas
 - 下一篇: python实验三答案_20194123