1. 程式人生 > >Python實現斐波那契數列與跳臺階變體

Python實現斐波那契數列與跳臺階變體

本篇記錄了斐波那契數列的Python實現:遞迴與迴圈兩種解法,以及一些化用的題目。

Python實現

遞迴

按傳統的遞迴方式,簡潔、優雅。寫出來卻是O(n2)O(n^2)的演算法

def fibo(n):
	"""肥波那契函式"""
    if n < 3:
    	return 1
    else:
        return fibo(n-1) + fibo(n-2)

O(n)O(n)的演算法

上面“簡潔”的演算法其實重複算了好多項。比如算fibo(6),它就算了三個fibo(3)、五個fibo(2)。從理論上分析,只要不多算,那就是O(n)O(n)

)的演算法——大約是算了n次fibo(n-1) + fibo(n-2)

思路也很簡潔:構建一個迴圈,在每次迴圈中,都有兩個變數儲存下一次迴圈的fibo(n-1)fibo(n-2)。當然,迴圈開始和終止的邊界條件是需要注意的。(拿幾個數去試一試就行了)

def fibo(n):
	if n < 3:
		return 1
	frist = 1
	second = 1
	third = 1  # 沒有這個會怎樣?
	count = 3
	while count <= n:
	    third = second + frist
	    frist = second
	    second =
third count += 1 return third if __name__ == '__main__': print(fibo(2)) # 1 print(fibo(6)) # 8

變體

跳臺階12

一個臺階總共有n級,如果一次可以跳一級或者兩級,求總共有多少種跳法?

  1. 假設存在函式ff,使得f(n)f(n)即為所求;
  2. 當臺階數n=0n=0n=1n=1時,f(n)=1f(n)=1(沒有跳法是為一種跳法);
  3. n&gt;1n\gt 1時,f(n)=f(n1)+f(n2)f(n) = f(n-1) + f(n-2)

看得出來是斐波那契數列嗎?就用上面的演算法就行了嗎?檢驗一下,兩級臺階的時候,總共2種跳法,寫個測試,發現輸出是1 != 2。。(好吧,肉眼可見)

def fibo(n):
	"""假設輸入值為整數"""
	[...]

def test_two():
    assert fibo(2) == 2  # error,1 != 2

怎麼回事?分析得不對嗎?原來,函式fibo(n)裡的n=1代表第一種情況,而這裡的第一種情況是臺階數n = 0。故可把輸入改成fibo(n - 1),或者把函式裡的引數改一改。

跳臺階123

一個臺階總共有n級,如果一次可以跳一級、兩級或者三級,求總共有多少種跳法?

改一下就好,理解不了就先用定義把寫個程式碼:

def result123(n):
	"""假設輸入值為整數"""
    if n <= 1: return 1
    elif n == 2: return 2
    elif n == 3: return 4
    frist = 1
    second = 2
    third = 4
    for i in range(4, n + 1):
        result = frist + second + third
        frist = second
        second = third        
        third = result
    return result

if __name__ == '__main__':
    print(result123(2))  # 2
    print(result123(3))  # 4
    print(result123(4))  # 7
    print(result123(5))  # 13

跳臺階23

一個臺階總共有n級,如果一次可以跳兩級或者三級,求總共有多少種跳法?

還是差不多,只是要從頭分析。可以檢驗一下:

def result23(n):
	"""假設輸入值為整數"""
    if n <= 4: return 1
    elif n <= 6: return 2
    frist = 1  # n = 4
    second = 2  # n = 5
    third = 2  # n = 6
    for i in range(7, n + 1):
        result = frist + second
        frist = second
        second = third        
        third = result
    return result

if __name__ == '__main__':
    print(result23(4))  # 1
    print(result23(6))  # 2
    print(result23(7))  # 3
    print(result23(10))  # 7