原文作者:sherlock31415931
原文标题:python 斐波那契数列 算法
发布时间:2021-01-18 15:43:56
斐波那契数,通常用F(n)表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给你 n ,请计算 F(n) 。
示例 1:
输入:2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1
纯递归
递归有两个基本要素:基例以及递归关系式。
基例:F(0) = 0,F(1) = 1,即递归结束的地方
递归关系式:F(n) = F(n-1) + F(n- 2)
def fib(n):
#base case
if n <= 1:
return n
elif n >= 2:
return fib(n-1) + fib(n-2)
然后根据python语法特性,可以缩写为一句话
def fib(n):
return fib(n-1) + fib(n-2) if n >= 1 else n
F(20) = F(19)+F(18)
F(19) = F(18)+F(17)
然后我们发现 F(18) 重复,即冗余结构。这样的运算时间会很大,
节点数 * 每个子问题所需要的时间 = 时间复杂度
显而易见,这种情况下为O(2^N)
纯递归的缺点就在于存在过多冗余结构。
递归加记忆,将指数级时间将为多项式级时间。
我们可以将已经出现计算好的存在一个备忘录里面,这样我们下一次计算之前,先去查一遍表就行,不需要再重新计算。
memo = {}
def fib(n):
#查表
if n in memo:
return memo[n]
#base case:
elif n <= 1:
return n
else:
ans = fib(n-1) + fib(n-2)
memo[n] = ans
return memo[n]
当然,上述的备忘录既可以采用数组,同时也可以用哈希表。
另外,如果追求完美一点,可以将基例存储到备忘录里面,这样可以减少一定程度的空间复杂度。
memo = {0:0,1:1}
这里介绍的是由上而下的方法,当然也可以是由下而上的。虽然比纯递归好,但是时间复杂度依然很高,leetcode上为1500-1600ms左右。
bottem-up-solution
def fib(n):
memo = {0:0,1:1}
for i in range(2,n+1):
memo[i] = memo[i-1] + memo[i-2]
return memo[n]
for循环的左边是因为备忘录里面已经有键0,1了,所以从2开始。然后我们最后要计算的是memo[n],i = n 所以要为n+1
这个的时间复杂度会大大降低,两者看似都是查表,但是由下而上的这种不会重新迭代函数,只会不断计算表。leetcode数据为36ms
算法方面的优化到此为止,但是关于空间复杂度可以更优化一点,
import sys
h = {0:0,1:1}
l = [0,1]
print(sys.getsizeof(h))
print(sys.getsizeof(l))
#232
#72
字典的空间复杂度远大于列表,所以可以更优化一点。单方面来讲,复杂度跟元素大小无关。跟元素个数有关。
def fib(n):
if n == 0:
return 0
memo[1 for i in range(n+1)]
memo[0],memo[1] = 0,1
for i in range(2,n+1):
memo[i] = memo[i-1] + memo[i-2]
return memo[n]
关于第一行生成len = n+1的原因,因为最后返回索引为n,而索引从0开始
而且除了列表生成器的表达,还可以
memo = [1] * (n+1)
之所以提取生成长度为n+1的列表,是为了防止列表索引不够,进行有序的替换。
因为是替换的,所以初始化列表的值是任取的,只要保证基例正确就行。
要小心的是,如果输入0没有开头的if语句是会报错的(for 循环)
还有就是力扣的很多时候判别的不准,大家只要往死里优化,看看几个最优解就行。不必苛求100%,大家可以复制几个100%,有些是运气100%,到你这就不是100%
最后,作为拓展,还有一种滚动变量的方法。
def fib(n):
if n == 0:
return 0
for i in range(n):
a,b = b,a+b
return a
这种方法显然不是最优解,但是值得一说的是,按照一些书中python的代码规范。这种结构可读性不好,建议少用。
大家觉得好的话,可以去github上给我点小星星呦
https://github.com/sherlcok314159/leetcode-python-3/blob/main/fibo.md
Post Views:
8