【题目描述】:
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。
n<=39
【要求】:
时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
一看到斐波那契数列,就想到递归,太简单了,三下五去二就做完了。虽然输出结果是正确的,但往往面试时越简单的题,陷阱越多,不是加有限制条件,就是考察编程语言的小技巧。这道看似简单的题就是加个时间和空间限制条件。递归虽然简单,但往往随着递归深度的增加,就更加消耗时间和空间。因为递归的时间和空间复杂度均为(O(2^n))。递归中间的数据一般都是压进栈中,但栈都是有最大空间限制。所以此题不能用寻常的递归解法。此外,这个题还有个文字陷阱就是整数n,整数是包含负整数,零和正整数。
首先看普通递归:
class Solution:
def Fibonacci(self, n):
if n==0:
return 0
elif n==1:
return 1
elif n>1:
return self.Fibonacci(n-1)+self.Fibonacci(n-2)
else:
return None
输出是没问题的,,但时间和空间肯定不满足。
非递归:
class Solution:
def Fibonacci(self, n):
if n<0:
return None
elif n==0:
return 0
elif n==1:
return 1
a=0
b=1
for i in range(0,n-1):
res = a+b
a=b
b=res
return res
非递归的算法复杂度为(O(n)),空间只多了a,b两个变量,这种方法完全符合时间和空间要求,正解。
但题目中n<=39这个条件不是不给的,说明还有其他解法。
尾递归法:
class Solution:
def tail_Fibonacci(self,n,res,temp):
if n<0:
return None
if n==0:
return res
else:
return self.tail_Fibonacci(n-1,temp,res+temp)
看着很眼熟,其实就是递归和非递归之间的折中方法,巧妙运用了参数来保存中间变量。在递归次数不大的情况下,可以运用这种方法。
空间换时间法:
class Solution:
def Fibonacci(self, n):
res = [0,1]
if n<0:
return None
if n>1:
for i in range(2,n+1):
res.append(res[i-2]+res[i-1])
return res[n]
这个方法是最笨的方法,思路和非递归一样。但为什么要列出来?因为在面试题中,经常要用到的一个思路就是:
用空间换时间,或者用时间换空间。