动态规划解题套路框架 :: labuladong的算法小抄 (gitee.io)今天学习这篇文章中的LeetCode509斐波那锲。
1、509斐波那锲
F[0] = 0, F[1] = 1, F(n) = F(n-1) + F(n-2)
方法1:暴力解法——递归
首先基线条件:F[0] = 0, F[1] = 1
循环条件:n>1
循环体:F(n) = F(n-1) + F(n-2)
class Solution:
def fib(self, n: int) -> int:
if n <= 1:
return n
else:
return self.fib(n-1) + self.fib(n-2)
缺点是时间复杂度高,每次都要计算2个值,O(2^N),因为其中有很多重复运算,因此可以设置一个数组来存储之前计算得到的值。
方法2:有记忆的优化递归
注意在初始化数组的时候是*(n+1),因为n从0开始的,然后就是增加一个判断,如果这个值计算过则直接返回。
class Solution:
def fib(self, n: int) -> int:
#动态规划
memo = [0]*(n+1)
return self.mfib(memo, n)
def mfib(self, memo, n):
if n <= 1:
memo[n] = n
return memo[n]
else:
if memo[n] != 0:
return memo[n]
else:
memo[n] = self.mfib(memo, n-1) + self.mfib(memo, n-2)
return memo[n]
因为只每个值计算了一次,因此 算法复杂度O(N)。
方法3:动态规划
动态规划相当于创建一个记录表,与递归不同,从底向上实现,由循环迭代完成。蛮奇妙的,需要注意在设置基值时memo[1]的设定,当输入=0时会越界,所以N=0的情况需要单独判定。也是O(N)空间复杂度也是O(N)?
class Solution:
def fib(self, n: int) -> int:
#动态规划
if n == 0:
return 0
else:
memo = [0]*(n+1)
memo[0] = 0
memo[1] = 1
if n <= 1:
return memo[n]
else:
for i in range(2, n+1):
memo[i] = memo[i-1] + memo[i-2]
return memo[n]
因为从通式来看,它之和两个状态有关,所以可以不用存储那么多的状态,可以进一步优化。
方法4:空间优化的动态规划
空间复杂度为O(1)
class Solution:
def fib(self, n: int) -> int:
#动态规划
if n <= 1:
return n
else:
pre = 0
cur = 1
sum1 = 0
for i in range(2, n+1):
sum1 = pre + cur
pre = cur
cur = sum1
return sum1