算法第28天|动态规划:基础理论、斐波那契数、爬楼梯、使用最小花费爬楼梯

今日总结

1、动态规划的五部曲要复习
2、动态规划的dp数组的含义及下标一定要定义清楚
3、动态规划的dp数组的递推公式一定要根据题目进行分析
4、动态规划的初始化一定要分析清楚(一定要在递推公式确定后再进行初始化分析)

动态规划的基础理论

1、动态规划是什么

动态规划的英文:Dynamic Programming,简称DP,**如果某一个问题有很多的重叠子问题,**使用动态规划是最有效的,

所以动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分与贪心,贪心没有状态推导,而是从局部直接选择最优

2、动态规划的解题步骤

状态转移公式(递推公式)很重要,但是动态规划不仅仅只有递推公式

动态规划的五部曲

(1)确定dp数组(dp table)以及下标的含义

(2)确定递推公式

(3)dp数组如何初始化

(4)确定遍历顺序

(5)举例推导dp数组

先确定递推公式再考虑初始化的原因:

一些情况是递推公式决定dp数组如何初始化

3、动态规划如何debug

最好的方式就是把dp数组打印出来,看看是不是按照自己思路推导的

(1)做动态规划的题目,写代码前一定要把状态转移在dp数组上的具体情况模拟一遍,做到心中有数,确定最后推出的是想要的结果

(2)然后再写代码,如果代码没通过就打印dp数组,看看是不是和自己预先推导的一样。

(3)如果打印的dp数组和自己推导的一样,就是自己的递归公式、初始化、遍历顺序有问题

(4)如果和自己预先模拟推导的不一,就是代码的实现细节有问题

斐波那契数

题目链接:509. 斐波那契数 - 力扣(LeetCode)

整体思路:

1、使用递归的方式做

2、使用动态规划dp做

dp五部曲

(1)确定dp数组及下标的含义

dp[i]的定义为:第i个数的斐波那契数值为dp[i];

(2)确定递推公式(就是当前的dp值与前边的有什么关系)

状态转移方程dp[i] = dp[i-1]+dp[i-2];

(3)qp数组初始化

dp[0]=0,dp[1]=1;

(4)确定遍历顺序

从状态转移方程可以看出当前dp[i]依赖于i-1,i-2,所以是从前往后遍历

(5)举例推导dp数组

当N=10:0,1,1,2,3,5,8,13,21,34,55

整体代码:

1、递归

cpp 复制代码
class Solution {
public:

    //1、确定递归的返回值、输入值
    //返回值当前的计算结果
    //输入值:当前的N
    int digui(int N)
    {
        //确定停止条件
        if(N==1)return 1;
        else if(N==0)return 0;
        //确定单层递归逻辑
        return digui(N-1)+digui(N-2);
    }
    int fib(int n) {
        return digui(n);
        
    }
};

2、动态规划(dp)

cpp 复制代码
class Solution {
public:
    int fib(int n) {
        //1、确定dp数组及下标含义:下标为当前的斐波那契数值
        vector<int>dp(n+1,0);
        //2、确定递推公式dp[i] = dp[i-1]+dp[i-2]
        //3、dp数组初始化
        if(n<1)return 0;
        dp[0]=0;
        dp[1]=1;
        if(n<=1)return n;
        //4、确定遍历顺序:前-->后
        //5、举例推导
        for(int i=2;i<n+1;i++)
        {
            dp[i] = dp[i-1]+dp[i-2];
        }
        return dp[n];
    }
};

爬楼梯

题目链接:70. 爬楼梯 - 力扣(LeetCode)

整体思路:

第一层楼梯:1

第二层楼梯:1+1;2

第三层楼梯:1+1+1(2,1,1);2+1(2,2,1);1+2(1,1,2)

第四层楼梯:1+1+1+1(3,1,1);2+1+1(3,2,1);1+2+1(3,3,1);1+1+2(2,1,2);2+2(2,2,2)

可以看出,当前i层的楼梯是通过i-1层的楼梯+1或者i-2层的楼梯+2的全部方法,所以当前层是与前边层的状态有关的,可以使用动态规划dp

(1)确定dp数组及下标

dp数组是当前楼梯的方法数,下标是当前楼梯的层数+1

(2)确定dp数组的递推公式

dp[i] = dp[i-1]+dp[i-2]

(3)确定dp数组的初始化

dp[1]=1.dp[2]=2

(4)确定dp数组遍历方向:从前往后

(5)举例

整体代码:

cpp 复制代码
class Solution {
public:
    int climbStairs(int n) {
        //(1)确定dp数组及下标

                //dp数组是当前楼梯的方法数,下标是当前楼梯的层数
    vector<int>dp(n+1,0);
    if(n==1)return 1;

        //(2)确定dp数组的递推公式

               // dp[i] = dp[i-1]+dp[i-2]

        //(3)确定dp数组的初始化

                //dp[1]=1.dp[2]=2
    dp[1]=1;
    dp[2]=2;
    for(int i=3;i<n+1;i++)
    {
        dp[i] = dp[i-1]+dp[i-2];
    }

        //(4)确定dp数组遍历方向:从前往后
    return dp[n];
        //(5)举例  
    }
};

使用最小花费爬楼梯

题目链接:746. 使用最小花费爬楼梯 - 力扣(LeetCode)

整体思路:

由题目可知:

(1)可以从0级台阶、1级台阶进行向上爬1级或者两级,支付当前台阶的cost

(2)最终到达楼梯顶,也就是需要通过最后一级台阶或者倒二台阶

(3)需要花费最少的cost,

(4)所以当前层最少一定是前边花费的最小-->动态规划

使用dp动态规划

(1)dp数组的含义:dp[i]表示当前层花费最少的cost

(2)dp数组的状态转移方程

dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])

(3)dp数组的初始化

dp[0]=cost[0];

dp[1] =cost[1];

(4)dp数组的遍历方式:从前到后

(5)举例

整体代码:

cpp 复制代码
class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        /*
        (1)dp数组的含义:dp[i]表示当前层花费最少的cost
                (2)dp数组的状态转移方程
                                dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
                (3)dp数组的初始化
                                dp[0]=cost[0];
                                dp[1] =cost[1];
                (4)dp数组的遍历方式:从前到后
        */
        vector<int>dp(cost.size()+1);
        dp[0] = 0;
        dp[1] = 0;
        for(int i=2;i<cost.size()+1;i++)
        {
            dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
        }
        return dp[cost.size()];
    }
};
相关推荐
CoovallyAIHub16 小时前
港大&字节重磅发布DanceGRPO:突破视觉生成RLHF瓶颈,多项任务性能提升超180%!
深度学习·算法·计算机视觉
CoovallyAIHub16 小时前
英伟达ViPE重磅发布!解决3D感知难题,SLAM+深度学习完美融合(附带数据集下载地址)
深度学习·算法·计算机视觉
聚客AI1 天前
🙋‍♀️Transformer训练与推理全流程:从输入处理到输出生成
人工智能·算法·llm
大怪v1 天前
前端:人工智能?我也会啊!来个花活,😎😎😎“自动驾驶”整起!
前端·javascript·算法
惯导马工2 天前
【论文导读】ORB-SLAM3:An Accurate Open-Source Library for Visual, Visual-Inertial and
深度学习·算法
骑自行车的码农2 天前
【React用到的一些算法】游标和栈
算法·react.js
博笙困了2 天前
AcWing学习——双指针算法
c++·算法
moonlifesudo2 天前
322:零钱兑换(三种方法)
算法
NAGNIP2 天前
大模型框架性能优化策略:延迟、吞吐量与成本权衡
算法
美团技术团队2 天前
LongCat-Flash:如何使用 SGLang 部署美团 Agentic 模型
人工智能·算法