碎碎念:开始动态规划了!加油!
 参考:代码随想录
动态规划理论基础
动态规划常见类型:
- 动规基础类题目
 - 背包问题
 - 打家劫舍
 - 股票问题
 - 子序列问题
 
解决动态规划问题应该要思考清楚的:
 动态规划五部曲:
- dp数组以及它下标的含义
 - 递推公式
 - dp数组如何初始化
 - 遍历顺序
 - 打印dp数组
 
509. 斐波那契数
题目链接
509. 斐波那契数
思想
动态规划五部曲:
- 确定dp数组以及下标的含义:dp[i] 第i个斐波那契数
 - 确定递推公式:dp[i] = dp[i-1]+dp[i-2]
 - dp数组的初始化:dp[0]=1 dp[1]=1
 - 确定遍历顺序:从前向后遍历
 - 打印dp数组:主要用来debug
 
由于求一个值只依赖前两个值,所以我们没必要维护一个数组,可以维护三个变量来完成状态转移。见python代码。
题解
// cpp
class Solution {
public:
    int fib(int n) {
        if (n == 0 || n == 1) return n;
        vector<int> dp(n+1);
        dp[0] = 0;
        dp[1] = 1;
        for (int 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
        
        prev1, prev2 = 0, 1
        for _ in range(2, n+1):
            cur = prev1 + prev2
            prev1, prev2 = prev2, cur
        
        return prev2
 
反思
本题简单,是因为题中已经给出了递推公式和初始值。
70. 爬楼梯
题目链接
70. 爬楼梯
思想
动态规划五部曲:
- 确定dp数组以及下标的含义:dp[i] 表示达到i阶梯有dp[i]种方法
 - 确定递推公式:dp[i] = dp[i-1]+dp[i-2] 爬到第i阶时,要么是从i-1一步过来的,要么从i-2一步迈两阶过来的
 - dp数组的初始化:dp[0]=0 dp[1]=1(dp[0]的取法主要是为了使得dp[2]为2,从含义上来说,到达0阶应该0种方法)也可以初始化dp[1]=1,dp[2]=2,不初始化dp[0]
 - 确定遍历顺序:从前向后遍历
 - 打印dp数组:主要用来debug
 
和上一题同理,也可以优化掉dp数组。
题解
// cpp
class Solution {
public:
    int climbStairs(int n) {
        if (n <= 1) return n;
        vector<int> dp(n+1);
        dp[1] = 1;
        dp[2] = 2;
        for (int i = 3; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }
};
 
# python
class Solution:
    def climbStairs(self, n: int) -> int:
        if n <= 1:
            return n
        
        prev1 = 1
        prev2 = 2
        for _ in range(3, n + 1):
            cur = prev1 + prev2
            prev1, prev2 = prev2, cur
        
        return prev2
 
反思
注意初始化那部分。
746. 使用最小花费爬楼梯
题目链接
746. 使用最小花费爬楼梯
思想
注意站在某个位置不花费cost,要爬上台阶的时候才会花费cost。
 如图所示,顶楼应该在3的位置。
 
 动态规划五部曲:
- 确定dp数组以及下标的含义:dp[i] 表示达到下标i的位置所需要的最小花费
 - 确定递推公式:dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2])
 - dp数组的初始化:dp[0]=0 dp[1]=0
 - 确定遍历顺序:从前向后遍历
 - 打印dp数组:主要用来debug
 
和上一题同理,也可以优化掉dp数组。
题解
// cpp
class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        vector<int> dp(cost.size() + 1);
        dp[0] = 0;
        dp[1] = 0;
        for (int i = 2; i <= cost.size(); i++) {
            dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
        }
        return dp[cost.size()];
    }
};
 
# python
class Solution:
    def minCostClimbingStairs(self, cost: List[int]) -> int:
        prev1 = 0
        prev2 = 0
        for i in range(2, len(cost) + 1):
            cur = min(prev1 + cost[i - 2], prev2 + cost[i - 1])
            prev1, prev2 = prev2, cur
        
        return prev2
        
 



















