递归原理
形式 - 函数内部调用函数本身
递 - 函数之间的传递参数
归 - 自动完成
终止 - 递归停止的条件
斐波那契数列
此案例可以延申很多。 类似兔子繁殖问题, 上楼梯问题等等
递归的方式实现
递归的方式是逆向的, 往后递归倒最底层的 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, 初始只有一对兔子, 第二个月每生出来也只有一对兔子