DP理论基础
重要知识点:
1.动规和贪心的区别:动规是由前一个状态推导出来的,而贪心是局部直接选最优的
2.动规五部曲:
1)确定dp数组(dp table)以及下标的含义
2)确定递推公式
3)dp数组如何初始化
4)确定遍历顺序
5)举例推导dp数组
509. 斐波那契数
1.题目
斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是: F(0) = 0,F(1) = 1 F(n) = F(n - 1) + F(n - 2),其中 n > 1 给你n ,请计算 F(n)
2.实现
注意空间优化
class Solution:
def fib(self, n: int) -> int:
# dp[i]表示第i个数的函数值
dp = {}
dp[0], dp[1] = 0, 1
# for i in range(2, n+1):
# dp[i] = dp[i - 1] + dp[i - 2]
# return dp[n]
# 优化:只需用两个数来记录前两项的数字:
if n < 2:
return dp[n]
for i in range(2, n+1):
tmp = dp[0] + dp[1]
dp[0] = dp[1]
dp[1] = tmp
return dp[1]
二刷补充
-
递归的时间复杂度计算:
时间复杂度 = 递归次数 * 每次递归的时间复杂度
对于递归次数:可以将递归抽象成二叉树,深度为m(第一层深度为1)的满二叉树的总节点数为 2^m - 1
递归算法的时间复杂度分析
(该文章以求解 x ^ n为例,来讲解如何求解时间复杂度,非常重要的面试题!!!) -
递归算法的空间复杂度计算:
空间复杂度 = 递归深度 * 每次递归的空间复杂度
70. 爬楼梯
1.题目
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
2.实现
class Solution:
def climbStairs(self, n: int) -> int:
dp = {}
dp[1], dp[2] = 1, 2
if n < 3:
return dp[n]
for i in range(3, n+1):
tmp = dp[1] + dp[2]
dp[1] = dp[2]
dp[2] = tmp
return dp[2]
3.拓展题目:
746. 使用最小花费爬楼梯