算法学习day38

算法学习day38

  • 1. 动态规划理论基础
  • 2. 力扣 509. 斐波那契数
    • 2.1 分析
    • 2.2 代码
  • 3. 力扣70. 爬楼梯
    • 3.1 分析
    • 3.2 代码
  • 4. 力扣746. 使用最小花费爬楼梯
    • 4.1 分析
    • 4.2 代码
  • 5.参考资料

1. 动态规划理论基础

1.什么是动态规划?
答:动态规划(Dynamic Programming) 简称DP,在动规划中每一个状态一定是由上一个状态推导出来的。

2. 动态规划的解题步骤是什么?
答:1.确定dp数组(dp table)以及下标的含义。2.确定递推公式。3.dp数组如何初始化。4.确定遍历顺序。5.举例推导dp数组。

2. 力扣 509. 斐波那契数

2.1 分析

动规五部曲:
使用一个一维dp数组来保存递归结果

1. 确定dp数组以及下标的含义
dp[i]的定义为:第i个数的斐波那契数值是dp[i]。

2. 确定递推公式
状态转移方程dp[i] = dp[i - 1] + dp[i - 2]

3. dp数组如何初始化
题目已经给定初始化了:dp[0] = 0; dp[1] = 1.

4. 确定遍历顺序
由递推公式dp[i] = dp[i -1] + dp[ i - 2]可知,dp[i]是依赖于dp[i - 1]和dp[ i - 2]的,所以遍历的顺序一定是从前往后遍历的。

5. 举例推导dp数组
当 N = 10 如下:
0 1 1 2 3 5 8 13 21 34 55

2.2 代码

class Solution {
public:
    int fib(int n) {
        if(n <= 1) return n; // 当n为0或1时,直接返回n本身
        vector<int> dp(n + 1); // 初始化一个大小为n+1的vector,用于存储斐波那契数列
        dp[0] = 0; // 初始化dp[0]为0
        dp[1] = 1; // 初始化dp[1]为1
        for(int i = 2 ; i <= n ; i++){ // 从2开始遍历到n
            dp[i] = dp[i -1] + dp[i - 2]; // dp[i]等于前两项之和
        }
        return dp[n]; // 返回第n项的值
    }
};

3. 力扣70. 爬楼梯

3.1 分析

动规五部曲:
使用一个一维dp数组来记录不同楼层的状态。

1. 确定dp数组以及下标的含义
dp[i]的定义为:爬到第i层楼梯,有dp[i]种方法。

2. 确定递推公式
状态转移方程dp[i] = dp[i - 1] + dp[i - 2]

3. dp数组如何初始化
dp[1] = 1; dp[2] = 2.

4. 确定遍历顺序
由递推公式dp[i] = dp[i -1] + dp[ i - 2]可知,dp[i]是依赖于dp[i - 1]和dp[ i - 2]的,所以遍历的顺序一定是从前往后遍历的。

5. 举例推导dp数组
当 N = 5 如下:
dp[i] : 1 2 3 5 8
下标i: 1 2 3 4 5

3.2 代码

class Solution {
public:
    int climbStairs(int n) {
        if(n <= 1) return n; // 当n=0或n=1时,结果为n
        vector<int> dp(n+1); // 定义一个长度为n+1的数组dp,存储到达每个台阶的方法数
        dp[1] = 1; // 到达第1个台阶的方法数为1
        dp[2] = 2; // 到达第2个台阶的方法数为2
        for(int i = 3 ; i <=n ; i++){ // 从第3个台阶开始计算
            dp[i] = dp[i - 1] + dp[i - 2]; // 到达第i个台阶的方法数等于到达第i-1个台阶的方法数和到达第i-2个台阶的方法数之和
        }
        return dp[n]; // 返回到达第n个台阶的方法数
    }
};

4. 力扣746. 使用最小花费爬楼梯

4.1 分析

动规五部曲:

1. 确定dp数组以及下标的含义
dp[i]的定义为:到达第i台阶所花费的最小体力为dp[i]。

2. 确定递推公式
dp[i - 1]跳到dp[i] 需要花费dp[i-1] + cost[i - 1]
dp[i - 2]跳到dp[i] 需要花费dp[i-2] + cost[i - 2]
选择最小的:
dp[i] = min(dp[i - 1]+ cost[i -1],dp[i - 2]+ cost[i - 2])

3. dp数组如何初始化
由题意:dp[0] = 0; dp[1] = 0.

4. 确定遍历顺序
模拟台阶,而且dp[i] 由dp[i - 1]和dp[i-2]推出,所以是从前到后遍历cost数组。

5. 举例推导dp数组
算法学习day38_第1张图片

4.2 代码

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        vector<int> dp(cost.size() + 1);  // 定义一个长度为cost.size()+1的vector
        dp[0] = 0;  // 初始化dp[0]为0
        dp[1] = 0;  // 初始化dp[1]为0
        for(int i = 2 ; i <=cost.size() ; i++){  // 从i=2开始遍历cost数组
            // dp[i]表示到达第i个台阶的最小花费
            // 由于可以从第i-1个台阶或者第i-2个台阶到达第i个台阶,因此取两者的最小值
            dp[i] = min(dp[i - 1] + cost[i - 1],dp[i - 2] + cost[i - 2]);
        }
        return dp[cost.size()];  // 返回到达最后一个台阶的最小花费
    }
};

5.参考资料

[代码随想录]

你可能感兴趣的:(算法,动态规划,c++,leetcode)