遞歸原理
形式 - 函數內部調用函數本身
遞 - 函數之間的傳遞參數
歸 - 自動完成
終止 - 遞歸停止的條件
斐波那契數列
此案例可以延申很多。 類似兔子繁殖問題, 上樓梯問題等等
遞歸的方式實現
遞歸的方式是逆向的, 往后遞歸倒最底層的 1+1 上再一層一層返回到低 k 層上的進行累加
原理圖示
遞的過程中, 相當於把任務分級, f3 因為 達到終止條件后 計算得到 2, 於是才有精力在計算 f2
於是基於此流程再依次重復計算 f3, f4
由此可見里面存在大量的重復計算的過程, 而且重復的次數隨着k的增加會更快程度的增加
而非遞歸的方式就不會有這種問題, 不論 k 你怎么取時間都較為穩定
代碼實現
# 1 1 2 3 5 8 13 21 .... def fib_test(k): # 求解第 k 個數的值 assert k > 0, u"k 必須大於0" if k in [1, 2]: return 1 return fib_test(k - 1) + fib_test(k - 2) if __name__ == '__main__': print fib_test(5) # 5 print fib_test(7) # 13
非遞歸的方式實現
非遞歸方式是正向, 從1+1 開始通過更新 k-1 和 k-2 實現
代碼實現
# 1 1 2 3 5 8 13 21 .... def fib_test(k): # 求解第 k 個數的值 assert k > 0, u"k 必須大於0" if k in [1, 2]: return 1 k_1 = 1 k_2 = 1 for i in range(3, k+1): # 便於理解的形式 # tmp = k_1 # k_1 = k_1 + k_2 # k_1 = tmp k_1, k_2 = k_1 + k_2, k_1 return k_1 if __name__ == '__main__': print fib_test(6) # 8 print fib_test(7) # 13
斐波那契問題其他類型 - 爬樓梯
反向思考, 對於最后一層台階來說, 有幾種可能性爬上來?
1. 從倒數第二層台階(k-1) 爬一級到最后一層台階
2. 從倒數第三層台階(k-2) 爬兩級到最后一層台階
同理對於倒數第二層台階來說, 有幾種可能性爬上來?
1. 從倒數第三層台階(k-1) 爬一級到最后一層台階
2. 從倒數第四層台階(k-2) 爬兩級到最后一層台階
由此可見還是滿足公式
f(k) = f(k-1) + f(k-2) 爬上每一層台階的可能性等於前一層和前兩次的可能加和
且 f(1) = 1 f(2) = 1 倒數第二和倒數第三爬到最后一層的可能性都為 1
斐波那契問題其他類型 - 生兔子
1 2 (1月兔) = 2
2 2 (1月兔) = 2
3 2 (1月兔) + 2(1月兔生- 3月兔) = 4
4 2 (1月兔) + 2(3月兔) + 2(1月兔生- 4月兔) = 6
5 2 (1月兔) + 2(3月兔) + 2(4月兔) + 2(1月兔生- 5月兔) + 2(3月兔生- 5月兔) =8
6 ......
上述規律可以看出, f(k) = f(k-1) + f(k-3) 因為是一對兔子生一對兔子
所以每個月的增量都應該是前前一個月的兔子數量 (兔子隔月生)
且滿足 f(1) = 2 , f(2) = 2, 初始只有一對兔子, 第二個月每生出來也只有一對兔子