代码随想录算法训练营第三十八天| 509. 斐波那契数 、70. 爬楼梯、746. 使用最小花费爬楼梯

今天开始动态规划了~   

动态规划的解题步骤

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

斐波那契数

题目链接:力扣

 由于题目给出了递归关系所以这题用递归法也很简单

    int fib(int n) {                //递归

        if(n<=1)
        return n;

        return fib(n-1)+fib(n-2);
    }

用动态规划:

  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]的,所以遍历顺序为从前往后
  5. 举例推导
int fib(int n)     //动规
    {
        if(n <= 1)
        return n;

        vectordp(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];
    }

 爬楼梯

题目链接:力扣

这题递推关系的推导,在b站评论里看到一个可以秒懂的:

在到达第n层的上一步,我们只有两个选择,走一步,或者走两步。
如果是走一步,我们需要先通过 f(n-1)种方式到达 n-1 层
如果是走两步, 我们需要通过 f(n-2)种方式到达第 n - 2 层
所以综上有 f(n) = f(n-2) + f(n-1)

 这题,如果可以知道递推关系,就会发现和上一题差不多。

  1. 确定dp数组以及下标的含义
    dp[i]: 爬到第i层楼梯,有dp[i]种方法
  2. 确定递推公式
    见上述。
  3. dp数组如何初始化
    dp[1] = 1,dp[2] = 2。
    注意:这里不考虑dp[0]如何初始化,只初始化dp[1] = 1,dp[2] = 2,然后从i = 3开始递推,这样比较符合dp[i]的定义。
  4. 确定遍历顺序
    从递推公式dp[i] = dp[i - 1] + dp[i - 2];中可以看出,遍历顺序一定是从前向后遍历的
  5. 举例推导dp数组
class Solution {
public:
    int climbStairs(int n) {

        if(n<=2) 
        return n;

        vector 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];

    }
};

使用最小花费爬楼梯 

题目链接:力扣 

  1. 确定dp数组以及下标的含义
    dp[i]的定义:到达第i台阶的最少花费为dp[i]。
  2. 确定递推公式
    可以有两个途径得到dp[i],一个是dp[i-1] 一个是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台阶所花费的最小体力为dp[0],
    同时,题目描述中明确说了 “你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。”
    也就是说 到达 第 0 个台阶是不花费的,但从 第0 个台阶 往上跳的话,需要花费 cost[0]。
    所以初始化 dp[0] = 0,dp[1] = 0;
  4. 确定遍历顺序
    因为是模拟台阶,而且dp[i]由dp[i-1]  dp[i-2]推出,所以是从前到后遍历cost数组就可以了。
  5. 举例推导dp数组
class Solution {
public:
    int minCostClimbingStairs(vector& cost) {

        vector dp(cost.size()+1);   //dp[i]的定义:到达第i台阶所花费的最少体力为dp[i]。
        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]);
            cout<<"dp[" <

你可能感兴趣的:(代码随想录刷题训练营,算法)