fibonacci的4种实现.把n=0也考虑在内
工具函数
计算运行时间与内存
def time_memory(func):
@functools.wraps(func)
def wrapper(*args, **kwargs):
tracemalloc.start()
start = time.perf_counter()
res = func(*args, **kwargs)
duration = (time.perf_counter() - start)*1000
current, peak = tracemalloc.get_traced_memory()
tracemalloc.stop()
print(f"{func.__name__} excution duration: {duration:.3f} ms")
print(f"{func.__name__} memory usage: current = {current / 1024:.3f} KB, peak = {peak / 1024:.3f} KB")
return res
return wrapper
1. base递归
最简单的递归实现,此种实现分线下来会有非常多重复子问题计算,导致时间复杂度为O(2^n)指数级别.
def fibonacci_base(n: int):
if n < 0:
raise ValueError(f'{n} is invalid')
elif n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci_base(n-1) + fibonacci_base(n-2)
测试样例
@time_memory
def test_base(n: int):
res = fibonacci_base(n)
print(res)
test_base(18)
运行结果
test_base excution duration: 3.812 ms
2. 数组缓存计算结果
考虑到base解法有不少重复计算的数值,可以用一个数组存放已经计算好的数值,递归计算时可以查看数组里面是否有之前已经计算好的值,使用空间换时间的方法,算法时间复杂度O(N) 空间复杂度O(N)
def do_fibonacci_e1(n: int, buffer: list[int]):
if n < 0:
raise ValueError(f'{n} is invalid')
if n == 0:
return buffer[0]
elif n == 1:
if buffer[1] == 0:
buffer[1] = 1
return buffer[1]
else:
if buffer[n] == 0:
buffer[n] = do_fibonacci_e1(n-1, buffer) + do_fibonacci_e1(n-2, buffer)
return buffer[n]
def fibonacci_e1(n: int):
if n < 0:
raise ValueError(f'{n} is invalid')
else:
buffer = [0] * (n+1)
return do_fibonacci_e1(n, buffer)
测试样例
@time_memory
def test_e1(n: int):
res = fibonacci_e1(n)
print(res)
test_e1(18)
运行结果
test_e1 excution duration: 0.097 m
3. 自底向上迭代替换递归
自底向上的解决办法,使用循环替代递归,时间复杂度O(N) 空间复杂度O(N) 循环实现消耗资源更少,所以时间更快.
代码:
def fibonacci_e2(n: int):
if n < 0:
raise ValueError(f'{n} is invalid')
elif n == 1:
return 1
# n >= 2 开始构建数组
dp = [0]*(n+1)
dp[0] = 0
dp[1] = 1
for i in range(2, n+1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
测试样例
@time_memory
def test_e2(n: int):
res = fibonacci_e2(n)
print(res)
test_e2(18)
运行结果
test_e2 excution duration: 0.052 ms
4. 终极解法,根据状态推导式 f(n) = f(n-1) + f(n-2) 只保留要前两个状态
进一步将时间复杂度降低到O(1)
def fibonacci_e3(n: int):
if n < 0:
raise ValueError(f'{n} is invalid')
elif n == 1:
return 1
pre = 0
curr = 1
for i in range(2, n+1):
res = pre + curr
pre = curr
curr = res
return res
测试样例
@time_memory
def test_e3(n: int):
res = fibonacci_e3(n)
print(res)
运行结果
test_e3 excution duration: 0.040 ms
669

被折叠的 条评论
为什么被折叠?



