代码随想录动态规划part01|动态规划理论基础、 509. 斐波那契数、 70. 爬楼梯 、746. 使用最小花费爬楼梯
- 动态规划基础
- 509. 斐波那契数
- 70.爬楼梯
- 746. 使用最小花费爬楼梯
动态规划基础
动规五部曲:
- dp数组以及下标的含义:dp[i][j] dp[i]
- 递推公式
- dp数组如何初始化
- 遍历顺序(背包、物品)
- 打印dp数组
509. 斐波那契数
leetcode题目链接
代码随想录文档讲解
思路
:
斐波那契数: 1 1 2 3 5 8
- 确定dp[i]含义:第i个斐波那契数的值为dp[i]
- 递推公式:dp[i] = dp[i-1] + dp[i-2]
- dp数组初始化:dp[0]=1 dp[1]=1
- 确定遍历顺序:从前向后
伪代码(C++)
:
vector<int> dp[n+1]
dp[0]=1; dp[1]=1;
for(i=2; i<=n; i++){
dp[i]=dp[i-1]+dp[i-2]
}
return dp[n]
python代码
:
class Solution:
def fib(self, n: int) -> int:
if n<= 1:
return n
dp = [0 for i in range(n+1)]
dp[1] = 1
for i in range(2,n+1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
70.爬楼梯
leetcode题目链接
代码随想录文档讲解
思路
:
楼梯一共有1阶台阶:1种;两阶台阶:2种;三阶台阶:3种(1阶+2阶)
递推关系:依赖于前两种状态,f(n)=f(n-1)+f(n-2)
- 确定递推数组的含义:达到第i阶有dp[i]种方法
- 递推公式:dp[i]=dp[i-2]+dp[i-1]
- dp数组初始化:dp[1]=1 ( dp[0]=1 n是正整数,dp[0]没有意义,令它为1,可使代码跑出正确的结果)
- 正序遍历,从前到后
其实就是 斐波那契数
伪代码(C++)
:
python代码
:
# dp代码
class Solution:
def climbStairs(self, n: int) -> int:
if n==1: return 1
dp = [1] * (n+1)
for i in range(2,n+1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
# 以前的代码
class Solution:
def climbStairs(self, n: int) -> int:
if n<2: return 1
a, b, sum = 1, 1, 0 # 0阶1阶台阶分别有1种
for _ in range(n-1):
sum = a+b
a, b = b, sum
return sum
# 以前的代码
class Solution:
def climbStairs(self, n: int) -> int:
if n<=2:
return n
curr = 0
prev1 = 2
prev2 = 1
for i in range(3,n+1):
curr = prev1 + prev2
prev1, prev2 = curr, prev1
return curr
746. 使用最小花费爬楼梯
leetcode题目链接
代码随想录文档讲解
思路
:
相当于爬楼梯题目的消费版
- dp数组的含义,到达i位置的花费为dp[i]
- dp[i]可由dp[i-1]跳1步或者dp[i-2]跳2步:dp[i] = min(dp[i-1] + cost[i-1] , dp[i-2] + cost[i-2])
- 初始化:dp[0]=0, dp[1]=0
- 每一个都是由前两个数组求得的,往前求
伪代码(C++)
:
python代码
:
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
dp = [0] * (len(cost)+1)
for i in range(2, len(cost)+1):
dp[i] = min(dp[i-1] + cost[i-1], dp[i-2]+cost[i-2])
return dp[len(cost)]