Studying-代码随想录训练营day33| 动态规划理论基础、509.斐波那契函数、70.爬楼梯、746.使用最小花费爬楼梯

第33天,动态规划开始,新的算法💪(ง •_•)ง,编程语言:C++

目录

动态规划理论基础

动态规划的解题步骤

动态规划包含的问题

动态规划如何debug

509.斐波那契函数

70.爬楼梯 

746.使用最小花费爬楼梯

总结 


动态规划理论基础

文档讲解:代码随想录动态规划理论基础

动态规划(Dynamic Programming),简称DP,通常用以解决某一问题有很多子问题的情况。

动态规划中每一个状态一定是由上一个状态推导出来的,这一点区别于贪心,贪心没有状态推导,而是从局部直接选出最优。

以背包问题为例,有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大?

在动态规划中dp[j]是由dp[j-weight[i]]推导出来的,然后取max(dp[j], dp[j - weight[i]] + value[i])。而贪心则是每次拿物品选一个最大的或者最小的就完事了,和上一个状态没有关系。所以贪心是解决不了动态规划的问题的。

动态规划的解题步骤

动态规划中,最重要的一个部分是状态转移公式,也即递推公式。但找到递推公式也只是一方面,我们在解题的时候,还需要构造dp数组,我们还需要确定dp数组中下标表示的含义,这样才能够有助于我们真正理解题目。

对于动态规划问题,我们可以把解题步骤拆解为如下五步:

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

解题过程中,依据上述5步进行。注意对dp数组的初始化,是在确定递推公式后的,因为有些初始化是要依据递推公式进行的。

动态规划包含的问题

动态规划一般包含的问题有:

  • 基础题目
  • 背包问题
  • 打家劫舍
  • 股票问题
  • 子序列问题

动态规划是一个很大的领域,对于后面的每一种问题,还需要进行单独的讲解。

动态规划如何debug

我们在解动态规划问题时,如果出现无法通过的时候,一定不要慌张,代码出现问题是很正常的。我们最重要的是不能让代码对我们而言是黑盒状态,就是我们都不确定它的运行顺序和结果。

最好的debug方式,就是把dp数组打印出来,看看结果究竟是不是按照自己思路推导的,又是哪一个部分出了错误。

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

在对动态规划问题进行debug时,我们一定要牢记三个问题:

  • 这道题目我举例推导状态转移公式了么?
  • 我打印dp数组的日志了么?
  • 打印出来了dp数组和我想的一样么?

牢记上述三个问题,基本就能够解决动态规划解题过程中遇到的问题。 


509.斐波那契函数

文档讲解:代码随想录斐波那契函数

视频讲解:手撕斐波那契函数

题目:

学习:本题是非常经典的数学题目之一,也是标准的动态规划题目。递推公式在题干中就已经给了我们,剩下的就是我们依照动规五部曲,逐步进行。

1.确定dp数组以及下标的含义:在这里我们可以定义一个vector型的dp数组,dp[i]定义为第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.举例推导dp数组:我可以依照我们上述构造的dp数组和递推关系,当n = 10时,dp数组应该为:0,1,1,2,3,5,8,13,21,34,55。如果发现结果不对,我们也可以通过打印dp数组来查看问题出在哪。

代码:

//时间复杂度O(n)
//空间复杂度O(n)
class Solution {
public:
    int fib(int n) {
        //动态规划,使用dp数组,存储斐波那契数列数值
        if(n < 2) return n; //0,1单独处理
        vector<int> dp(n + 1); //从0-N,dp(n)表示第n个数的斐波那契数值
        dp[0] = 0;
        dp[1] = 1;
        for(int i = 2; i <= n; i++){
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n];
    }
};

代码:对于本题来说,实际上也可以不适用dp数组,我们只需要维护两个值就可以了

//时间复杂度O(n)
//空间复杂度O(1)
class Solution {
public:
    int fib(int n) {
        //动态规划,不使用dp数值,只找到第n个值
        if(n < 2) return n;
        int dp0 = 0;
        int dp1 = 1;
        int sum;
        for(int i = 2; i <= n; i++) {
            sum = dp0 + dp1;
            dp0 = dp1;
            dp1 = sum;
        }
        return dp1;
    }
};

代码:本题还可以使用递推公式进行,代码极度简便,但并不好想。

//时间复杂度O(2^n)
//空间复杂度O(n)
class Solution {
public:
    int fib(int n) {
        //递归法,非常恐怖
        if(n < 2) return n;
        else return fib(n - 1) + fib(n - 2);
    }
};

70.爬楼梯 

文档讲解:代码随想录爬楼梯

视频讲解:手撕爬楼梯

题目:

学习:本题实际上是斐波那契数的变种,递推公式都是一样的。这也可见动态规划问题能够想出递推公式确认是十分重要的。

对于本题来说,由于一次可以爬1或2个台阶,因此对于第3层台阶来说,可以从第一层爬2层台阶到达,也可以从第二层爬1层台阶到达。而到达第一层和第二层的种类分别是dp[1]和dp[2]因此,到达第三层的种类就为dp[1]+dp[2],之后的第四层也是如此,能够通过从第二层爬2阶到达,也能够通过从第三层爬1阶到达……

最后就能够得到同样的递推公式dp[n] = dp[n - 1] + dp[n - 2]。但要注意本题中与斐波那契数不同的式dp[0]在本题中是没有意义的,虽然我们给dp[0]赋值为1(因为dp[2]=2)也能够解决问题,但是dp[0]是没有实际意义的,因此本题更推荐给dp[1]和dp[2]进行初始化。

代码:

//时间复杂度O(n)
//空间复杂度O(n)
class Solution {
public:
    int climbStairs(int n) {
        //动态规划
        //1.确定dp数组以及下标的含义
        vector<int> dp(n + 1); //dp(n)表示爬n阶的方法
        //2.确定递归条件:dp(n) = dp(n - 1) + dp(n - 2);
        //3.dp数组初始化,因为dp(0)是没有意义的,且n也不会等于0,因此不需要初始化0
        if(n <= 1) return n;
        dp[1] = 1;
        dp[2] = 2;
        //4.确定遍历顺序
        for (int i = 3; i <= n; i++) {
            dp[i] = dp[i - 1] + dp[i - 2];
            //5.举例推导dp数组(打印dp数组)
            //cout << dp[i] << endl;
        }
        return dp[n];
    }
};

746.使用最小花费爬楼梯

文档讲解:代码随想录使用最小花费爬楼梯

视频讲解:手撕使用最小花费爬楼梯

题目:

学习:本题我们需要注意题干中的两个点:1.cost[i],是从i个台阶向上爬需要支付的费用,也就是我们只有向上爬了,才需要支付费用,我们站在i台阶上,是不需要支付cost[i]的。2.到达楼梯顶部不是指第最后的下标(cost.size() - 1)个台阶,实际上根据例子我们可以发现,是最后一个台阶还要再上一个台阶才是顶部的位置。

基于此,我们可以通过递归五部曲来求解本题。

1.确定dp数组以及下标的含义:我们可以构造一个vector型dp数组,其中dp[i]应该定义为到达第i个台阶所花费的最小体力,这样我们最后求出的dp[cost.size()]才是到达顶部的花费最小体力。

2.确定递推公式:对于第i个台阶来说,有两个途径能够得到dp[i],一个是dp[i - 1],一个是dp[i - 2]而我们需要得到最小的,因此dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])。

3.初始化dp数组:通过递推公式我们知道,至少需要两个数才能够推出后面的值,因此我们可以初始化dp[0] 和 dp[1](注意本题中题干给出了0下标的含义)

4.确定遍历顺序:显然本题也是从前往后进行遍历。

5.举例推导dp数组:

代码:

//时间复杂度O(n)
//空间复杂度O(n)
class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        //动态规划
        //1.确定dp数组及下标含义
        vector<int> dp(cost.size() + 1); //dp[n]表示上到第n个台阶所要消耗的最小花费
        //2.确定递推公式 dp[n] = min(dp[n - 1] + cost[n - 1], dp[n - 2] + cost[n - 2]);
        //3.dp数组初始化(规定cost.size() >= 2)
        dp[0] = 0; //爬的时候才消耗费用
        dp[1] = 0;
        //4.确定遍历顺序
        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()];
    }
};

总结 

动态规划开始,牢记动态五部曲,做题不慌张。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/786906.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

文华财经红绿多空趋势量化买卖点指标公式源码

LC:REF(CLOSE,1); RSI1:SMA(MAX(CLOSE-LC,0),13,1)/SMA(ABS(CLOSE-LC),13,1)*100; RSIF:90-RSI1,COLOR33DD33; A4:((C-LLV(L,33))/(HHV(H,33)-LLV(L,33)))*67; ABC22:LLV(LOW,10); ABC33:HHV(HIGH,25); 动力线:EMA((CLOSE-ABC22)/(ABC33-ABC22)*4,4); RSV:(C-LLV(L,9))/…

前端入门知识分享:如何在HTML或CSS文件中引用CSS文件。

阅读提示&#xff1a;本文仅仅仅适用于刚刚接触HTML和CSS的小白从业者&#xff0c;新人爱好者。自觉身份不符的老鸟们&#xff0c;尽快绕行吧&#xff01; 什么是CSS&#xff1f;什么是CSS文件。 CSS&#xff0c;全称为Cascading Style Sheets&#xff08;层叠样式表&#xff…

淮北在选择SCADA系统时,哪些因素会影响其稳定性?

关键字:LP-SCADA系统, 传感器可视化, 设备可视化, 独立SPC系统, 智能仪表系统,SPC可视化,独立SPC系统 在选择SCADA系统时&#xff0c;稳定性是一个关键因素&#xff0c;因为它直接影响到生产过程的连续性和安全性。以下是一些影响SCADA系统稳定性的因素&#xff1a; 硬件质量…

2024机器遗忘(Machine Unlearning)技术分类-思维导图

1 介绍 机器遗忘&#xff08;Machine Unlearning&#xff09;是指从机器学习模型中安全地移除或"遗忘"特定的数据点或信息。这个概念源于数据隐私保护的需求&#xff0c;尤其是在欧盟通用数据保护条例&#xff08;GDPR&#xff09;等法规中提出的"被遗忘的权利…

1、课程导学(react+区块链实战)

1、课程导学&#xff08;react区块链实战&#xff09; 1&#xff0c;课程概述&#xff08;1&#xff09;课程安排&#xff08;2&#xff09;学习前提&#xff08;3&#xff09;讲授方式&#xff08;4&#xff09;课程收获 2&#xff0c;ibloackchain&#xff08;1&#xff09;安…

前端Debugger时复制的JS对象字符转JSON对象

前端debugger时&#xff0c;复制的对象在控制台输出时是如下格式&#xff0c;需要转换为对象格式来进行验证操作 bridgeId : 4118 createBy : null createTime : "2023-03-24 10:35:26" createUserId : 1 具体实现代码&#xff1a; // 转换transform (text) {l…

yolov8 人体姿态识别

引言 在计算机视觉的各种应用中&#xff0c;人体姿态检测是一项极具挑战性的任务&#xff0c;它能够帮助我们理解人体各部位的空间位置。本文将详细介绍如何使用 YOLOv8 和 Python 实现一个人体姿态检测系统&#xff0c;涵盖模型加载、图像预处理、姿态预测到结果可视化的全流…

业务咨询方案 + IT落地方案建议设计

近期&#xff0c;在深入探索咨询方案的实施与落地路径时&#xff0c;体会到了一系列心得与启示&#xff0c;旨在为未来的项目实践提供可借鉴的蓝本。 咨询方案的精髓&#xff0c;在于“业务引领&#xff0c;IT支撑”的核心理念。所以方案的前提是在于业务的梳理&#xff1b; …

侯捷C++面向对象高级编程(上)-11-虚函数与多态

1.虚函数 2.virtual 3.继承&#xff0b;复合关系下的构造和析构 4.委托&#xff0b;继承

【深度学习】图形模型基础(5):线性回归模型第五部分:多变量线性回归模型

1.引言 当我们从基础的线性模型 y a b x error y a bx \text{error} yabxerror 转向更复杂的模型 y β 0 β 1 x 1 β 2 x 2 … error y \beta_0 \beta_1 x_1 \beta_2 x_2 \ldots \text{error} yβ0​β1​x1​β2​x2​…error 时&#xff0c;我们面临了诸多…

汇聚荣拼多多实力怎么样?

汇聚荣拼多多实力怎么样?拼多多作为中国电子商务行业的后起之秀&#xff0c;其市场表现和商业策略引起了广泛的关注。在回答“汇聚荣拼多多实力怎么样?”这一问题时&#xff0c;我们可以明确地看到&#xff0c;拼多多通过其独特的商业模式和创新策略&#xff0c;在竞争激烈的…

2024-07抖音/快手/小红书/视频号/美团无人直播技术:最新不封号无人直播的操作方法详细介绍

2024年最新研究出来的无人直播技术&#xff0c;目前不封号&#xff0c;用途大大的&#xff0c;可带货&#xff0c;可引流&#xff0c;可获客。 手机自动直播源码通常涉及到实时流媒体技术和应用开发&#xff0c;它涉及以下几个关键部分&#xff1a; 摄像头接入&#xff1a;使用…

Mysql-内置函数

一.什么是函数&#xff1f; 函数是指一段可以直接被另外一段程序调用的程序或代码。 mysql内置了很多的函数,我们只需要调用即可。 二.字符串函数 MySQL中内置了很多字符串函数: 三.根据需求完成以下SQL编写 由于业务需求变更,企业员工的工号,统一为5位数,目前不足5位数的全…

[极客大挑战 2019]RCE ME

[极客大挑战 2019]RCE ME <?php error_reporting(0); if(isset($_GET[code])){$code$_GET[code];if(strlen($code)>40){die("This is too Long.");}if(preg_match("/[A-Za-z0-9]/",$code)){die("NO.");}eval($code); } else{highlight_f…

施罗德数列SQL实现

在组合数学中,施罗德数用来描述从(0,0)到(n,n)的格路中,只能使用(1,0)、(0,1)、(1,1)三种移动方式,始终位于对角线下方且不越过对角线的路径数 DECLARE n INT 10 DECLARE i INT DECLARE rst INT DECLARE old INT1CREATE TABLE #rst (i INT ,rst int )INSERT INTO #rst values(…

ozon跨境电商可以做吗,俄罗斯ozon跨境电商可不可以做

当今全球化的浪潮下&#xff0c;跨境电商已成为连接世界各地消费者与商家的桥梁&#xff0c;为无数企业开辟了全新的市场蓝海。俄罗斯&#xff0c;作为世界上最大的国家之一&#xff0c;其电商市场近年来蓬勃发展&#xff0c;尤其是ozon平台&#xff0c;作为俄罗斯本土的电商巨…

hash

哈希 key->value&#xff0c;借助离散化的思想对数据进行映射&#xff0c;可视为用value代表原本的key 在C中&#xff0c;可使用map当做哈希表使用&#xff0c;将std::hash当做哈希函数使用 hash<Typename>name; size_t valuename(key);数字哈希 哈希函数的设计 方…

科普文本分类背后的数学原理——最新版《数学之美》第14、15章读书笔记

新闻分类&#xff0c;或广义上的文本分类&#xff0c;其核心任务是根据文本内容将相似文本聚合在同一类别中。在新闻领域&#xff0c;这意味着将报道划分为财经、体育、军事等不同主题。人类执行此任务时&#xff0c;通过阅读和理解新闻的主旨来进行归类。然而&#xff0c;作者…

软件工具网站推荐

1.菜鸟工具 菜鸟工具 - 不止于工具菜鸟工具&#xff0c;为开发设计人员提供在线工具&#xff0c;网址导航&#xff0c;提供在线PHP、Python、 CSS、JS 调试&#xff0c;中文简繁体转换&#xff0c;进制转换等工具。致力于打造国内专业WEB开发工具&#xff0c;集成开发环境&…