昨天看到一篇文章,题目好像叫做"如果面试官问到你斐波拉契数列,千万不要高兴太早",正好今天在leetcode上遇到了这道题,就记录一下心得。
方法1
常规递归法,这种递归的方法坏处就是重复计算,比如f(7) = f(6) +f(5)
在计算f(6)的时候其实也计算过f(5),然后还要重新计算一遍f(5)
,相当于一棵分裂的二叉树,计算次数呈指数上升。
class Solution1:
def fib(self, N):
if N <=1:
return N
else:
return self.fib(N-1)+self.fib(N-2)
方法2
迭代法 ,这个很简单可行,但需要O(n)的空间复杂度
class Solution2:
def fib(self, N):
array = [i for i in range(N+1)]
for i in range(2,N+1):
array[i] = array[i-1]+array[i-2]
return array[-1]
方法3
也是迭代法,只不过两个变量循环利用
class Solution3:
def fib(self, N):
if N <=1:
return N
left = 0
right =1
for i in range(2,N+1):
tmp = right
right = left + right
left = tmp
return right
方法4
该方法为改进的方法1,因为方法1的缺点是每次计算过的f(n)会被重新计算,所以我们只需要将计算过的f(n)保存起来就行了,用数组的第i个元素表示f(i)
class Solution4:
def fib(self, N):
array =[i for i in range(N+1)]
return self.fibola(array, N)
def fibola(self, array, N):
if N <= 1:
return N
array[N] = self.fibola(array, N-1) + array[N-2]
return array[N]
很容易理解这个递归,比如计算f(7) = f(6) + f(5)时,只需要对f(6进行递归计算,f(5)在f(6)计算的时候会产生。又因为数组时可变对象,递归每次都是对地址上的元素进行修改,所以这个数组就相当于是全局变量。所以也可以按照下面的写法
class Solution:
def fib(self, N):
self.array =[i for i in range(N+1)]
return self.fibola(N)
def fibola(self, N):
if N <= 1:
return N
self.array[N] = self.fibola( N-1) + self.array[N-2]
return self.array[N]