算法第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()];
    }
};
相关推荐
医工交叉实验工坊35 分钟前
R 语言 ComplexUpset 包实战:替代 Venn 图的高级集合可视化方案
算法·r语言
东皇太星1 小时前
模运算(密码学/数论/算法)
数据结构·算法·密码学
一水鉴天2 小时前
整体设计 修订 之1 三“先”之“基” 与范畴重构:康德先验哲学的批判性程序化实现
java·人工智能·算法
剪一朵云爱着2 小时前
PAT 1086 Tree Traversals Again
算法·pat考试
JuneXcy3 小时前
流程控制语句(3)
c语言·算法
Mercury_Lc3 小时前
【贪心 或 DFS - 面试题】小于n最大数
数据结构·c++·算法
凤年徐3 小时前
【数据结构】LeetCode160.相交链表 138.随即链表复制 牛客——链表回文问题
c语言·数据结构·c++·算法·leetcode·链表
qq_12498707533 小时前
基于改进蜂群优化算法的高频金融波动率预测系统 (源码+论文+部署+安装)
python·算法·金融·毕业设计·蜂群优化算法
艾莉丝努力练剑3 小时前
【C语言16天强化训练】从基础入门到进阶:Day 14
java·c语言·学习·算法
元亓亓亓4 小时前
LeetCode热题100--98. 验证二叉搜索树--中等
算法·leetcode·职场和发展