1. 普通递归实现
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n - 1) + fibonacci(n - 2)
2. 记忆化(Memoization)优化实现
def fibonacci_memoized(n, memo={}):
if n <= 1:
return n
if n not in memo:
memo[n] = fibonacci_memoized(n - 1, memo) + fibonacci_memoized(n - 2, memo)
return memo[n]
3. 优化思路
- 普通递归:每次计算
fibonacci(n)
时,都会重复计算fibonacci(n - 1)
和fibonacci(n - 2)
,存在大量的重复计算。例如计算fibonacci(5)
,fibonacci(3)
会被计算两次,fibonacci(2)
会被计算三次等。随着n
的增大,重复计算量呈指数级增长。
- 记忆化优化:使用一个字典
memo
来存储已经计算过的斐波那契数。每次计算前先检查字典中是否已有结果,如果有则直接返回,避免重复计算。这样就将许多重复的子问题计算次数减少到1次。
4. 时间复杂度变化
- 普通递归:时间复杂度为$O(2^n)$。因为每次调用函数都会产生两个新的递归调用,形成一个高度为
n
的二叉树结构,节点数(即计算次数)约为$2^n$。
- 记忆化优化:时间复杂度为$O(n)$。因为每个
n
只被计算一次,计算过的结果被存储在memo
中,之后再次计算时直接从memo
获取,总共需要计算n
次,所以时间复杂度为线性。