题目描述
解法
最开始想,这道题肯定用递归啊
class Solution:
def fib(self, n: int) -> int:
if n < 0:
return None
if n == 0:
return 0
if n == 1:
return 1
return self.fib(n-1) + self.fib(n-2)
但是不是这么简单的,这样会超时!!很多f(n)会被重复计算。所以来找一找规律。
f(n)其实只与f(n-1), f(n-2)有关,所以我们就考虑用a和b记录这两个值。
最开始的时候,n=0,a=0;n=1,b=1(红色标记),通过a+b就能得到f2=1。那么现在就是有a=f0,b=f1,f2。
这时我们要计算f3,实际上只需要f1和f2,f0可以抛弃了。所以将a变为f1,b变为f2(黄色标记)。
依次类推,不断更新a和b,得到最终的结果,这过程中,也并没有重复的计算导致时间复杂度变高。
那么,如何实现这个过程呢?
就可以考虑用for循环,俗话说万丈高楼平地起。我们就从0和1建起,建到n。
先看要循环几次?
我们看图,当算f2时,要更新一次ab(红);f3时,要更新2次ab(红黄);f4时,要更新3次ab(红黄蓝)
…
f6时,更新了5次ab
所以循环的次数就是n-1,所以就是for i in range(n-1).
次数确定后,在for要写什么呢?
那就是更新ab啦!
看图可知,新一轮的a是等于旧一轮的b,新一轮的b是等于旧一轮a+b的结果。
好,上代码!
class Solution:
def fib(self, n: int) -> int:
if n < 0:
return None
if n == 0:
return 0
if n == 1:
return 1
a,b = 0,1
for i in range(n-1):
# 当前得数
num = a+b
# 更新ab
a = b
b = num
return num
通过!!循环了n-1次,所以时间复杂度为O(n)。
注意:
在 剑指offer 系列中,多加了个要求
我说这方法这么完美,怎么会出错呢???
那么就最后return的地方修改一下就好了!
总结:
递归的思路很简单,但是时间复杂度高,很多重复计算。
刚开始,其实是考虑用哈希表存储fn的值,但是n很大的时候,需要的空间也很大,这就是用空间换取时间。
最终的方法,时间空间都很nice,主要还是要学会找规律,不会找怎么办?看答案,理解答案,记住答案。