理论基础
动态规划:当前状态由前面的状态推导而来
贪心:局部选最优动态规划5步曲
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
509. 斐波那契数
力扣链接
动态规划5步曲
- 确定dp数组(dp table)以及下标的含义:dp[i]是F(i)
- 确定递推公式,dp[i] = dp[i-1]+dp[i-2] i>1
- dp数组如何初始化 dp[0]=0 dp[1]=1
- 确定遍历顺序【从前往后】
- 举例推导dp数组
【动态规划】
时间复杂度:O(n) ,空间复杂度:O(n)
class Solution:
def fib(self, n: int) -> int:
if n == 0: return 0 #否则dp[1]就有问题
dp = [0] * (n+1)
dp[0] = 0
dp[1] = 1
for n in range(2,n+1):
dp[n] = dp[n-1] + dp[n-2]
return dp[n]
#只用维护两个数值 ,时间复杂度:O(n) ,空间复杂度:O(1)
class Solution:
def fib(self, n: int) -> int:
if n <= 1 :
return n
prev1, prev2 = 0, 1
for _ in range(2, n+1):
cur = prev1 + prev2
prev1, prev2 = prev2, cur
return prev2
【递归法】时间复杂度:O(2^n) ,空间复杂度:O(n)
class Solution:
def fib(self, n: int) -> int:
if n<2:
return n
return self.fib(n-1)+self.fib(n-2)
70. 爬楼梯
力扣链接
动态规划5步曲
- 确定dp数组(dp table)以及下标的含义: dp[i]:爬到第i个楼梯,有dp[i]种办法
- 确定递推公式,dp[i] = dp[i-1]+dp[i-2] i>1
- dp数组如何初始化 dp[1]=1 dp[2]=2
- 确定遍历顺序【从前往后】
- 举例推导dp数组
# 空间复杂度为O(n)版本
class Solution:
def climbStairs(self, n: int) -> int:
if n <= 1:
return n
dp = [0] * (n + 1)
dp[1] = 1
dp[2] = 2
for i in range(3, n + 1):
dp[i] = dp[i - 1] + dp[i - 2]
return dp[n]
# 空间复杂度为O(1)版本
class Solution:
def climbStairs(self, n: int) -> int:
if n<3:
return n
prev1, prev2 = 1, 2
for i in range(3,n+1):
cur = prev1 + prev2
prev1, prev2 = prev2, cur
return prev2
746. 使用最小花费爬楼梯
力扣链接
动态规划5步曲
- 确定dp数组(dp table)以及下标的含义:
cost[i] :第 i 个阶梯对应着一个非负数的体力花费值;dp[i]:到达第i台阶所花费的最少体力- 确定递推公式,dp[i] = min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2]) i>2
- dp数组如何初始化 dp[1]=cost[0] dp[2]=2
- 确定遍历顺序【从前往后】
- 举例推导dp数组