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

news2024/9/25 21:28:36

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

总结 

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MSPM0G3507——时钟配置(与32关系)

先将32端时钟配置分为1&#xff0c;2&#xff0c;3如图 1是PSC左边未经分频的时钟源&#xff08;HZ&#xff09; 2是经过PSC分频的时钟信号&#xff08;HZ&#xff09; 3是最终的输出信号&#xff08;HZ&#xff09; 3输出的是一个定时器周期的HZ&#xff0c;可以转换成时间 …

哨兵系统:一套实时灵活可配置化的业务指标监控系统

简介: 在KOO分期的线下业务中&#xff0c;需要对很多关键业务指标进行实时监控&#xff0c;并需要根据一定的数据格式&#xff0c;通过企微机器人发往对应的企微群&#xff0c;因此KOO分期技术团队在KOO业务指标库之上&#xff0c;搭建了一套KOO分期业务指标监控系统&#xff…

ppt接单渠道大公开‼️

PPT 接单主要分两种&#xff1a;PPT 模板投稿和PPT 定制接单&#xff0c;我们先从简单的 PPT 模板投稿说起。 PPT 模板投稿 利用业余时间&#xff0c;做一些 PPT 模板上传到平台&#xff0c;只要有人下载你的模板&#xff0c;你就有收入。如果模板质量高&#xff0c;简直就是一…

Hadoop-19 Flume Agent批量采集数据到HDFS集群 监听Hive的日志 操作则把记录写入到HDFS 方便后续分析

章节内容 上一节我们完成了内容&#xff1a; Flume 启动测试Flume Conf编写Flume 测试发送和接收数据 背景介绍 这里是三台公网云服务器&#xff0c;每台 2C4G&#xff0c;搭建一个Hadoop的学习环境&#xff0c;供我学习。 之前已经在 VM 虚拟机上搭建过一次&#xff0c;但…

高德API接入安卓相关问题说明

高德API接入安卓相关问题说明 我们都在怀念过去&#xff0c;失去后我们才懂得珍惜&#xff0c;有些人或事早已经远去&#xff0c;可是还是会想起曾经拥有的岁月&#xff0c;会是一种喜悦&#xff0c;会是一种遗憾…… 目前Android开发已经普遍使用Android Studio&#xff0c;开…

优思学院|当今的丰田精益生产模式落伍了吗?

丰田曾经是全球销量最大的汽车制造商&#xff0c;不过现在却被挖苦为可能会成为下一个汽车界的“诺基亚”。 丰田的前CEO丰田章男对于电动汽车的前景持极度怀疑态度&#xff0c;今年4月他下台&#xff0c;由年轻14岁的佐藤恒治接任。这一变动反映了丰田对电动汽车态度的180度大…

streamlit table转置显示

streamlit table转置显示,并且原始的表头放在最左侧 原始表格 代码 import streamlit as st import pandas as pd# 创建一个示例 DataFrame data {Column1: [1, 2, 3],Column2: [4, 5, 6],Column3: [7, 8, 9] } df pd.DataFrame(data)# 转置 DataFrame transposed_df df.T…

进程,进程的调度,进程的调度算法(详解)ฅ( ̳• · • ̳ฅ)

目录 &#x1f607;进程的概念&#xff1a; &#x1f61a;进程的组成&#xff1a; &#x1f970;进程的调度&#xff1a; 一.进程调度的概念&#xff1a; 二.进程调度的方式&#xff1a; 三.进程调度的时机&#xff1a; &#x1f92a;进程的调度算法&#xff1a; 一.先…

如何通过运动改善老年人的腿部肌肉力量?

老年人腿部肌肉力量的重要性 随着年龄的增长&#xff0c;肌肉自然会逐渐萎缩&#xff0c;特别是腿部肌肉。腿部肌肉的强弱直接影响到老年人的行走能力、平衡能力和日常生活的自理能力。因此&#xff0c;通过适当的运动来改善和增强腿部肌肉力量对于老年人来说至关重要。 适合老…

1Panel安装教程:使用Linux服务器安装1Panel面板全流程

使用阿里云服务器安装1Panel面板全流程&#xff0c;云服务器操作系统为CentOS 7.9&#xff0c;安装1Panel非常简单&#xff0c;先执行1Panel安装命令&#xff0c;然后在云服务器安全组中开通1Panel默认端口号、安全入口、用户名和密码等操作&#xff0c;阿里云百科整理详细安装…

前端八股文 跨域

前端跨域和常见解决方案 一、什么是跨域 同源策略是一个重要的安全策略&#xff0c;它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的 资源进行交互。它能帮助阻隔恶意文档&#xff0c;减少可能被攻击的媒介。 有一点必须要注意&#xff1a;跨域并不是请求发不…

Unity插件 Unitask学习日志

Unity插件 Unitask学习日志 下载地址 https://github.com/Cysharp/UniTask点击这里可以查阅中文文档 在Unity 2020,2021 中使用UPM下载会找不到&#xff0c;可以使用2022版本的unity可以在upm中找到。 安装方式&#xff1a; 下载zip之后解压&#xff0c; 复制Plugins 到Uni…

化工厂定位系统有哪些功能?

有伙伴了解化工厂定位系统吗&#xff1f;相信很多小伙伴都没有听说过&#xff0c;感觉离我们的生活比较远&#xff0c;事实上化工厂定位系统也是默默的在保护我们的安全。今天新锐科创就给大家介绍一下这个系统&#xff0c;让大家简单的了解一下。 大家都知道化工厂一直是一个比…

【LLM大模型】如何在LlamaIndex中使用RAG?

如何在LlamaIndex中使用RAG 什么是 Llama-Index LlamaIndex 是一个数据框架&#xff0c;用于帮助基于 LLM 的应用程序摄取、构建结构和访问私有或特定领域的数据。 如何使用 Llama-Index ? 基本用法是一个五步流程&#xff0c;将我们从原始、非结构化数据导向基于该数据生成…

本地部署 SenseVoice - 阿里开源语音大模型

本地部署 SenseVoice - 阿里开源语音大模型 1. 创建虚拟环境2. 克隆代码3. 安装依赖模块4. 启动 WebUI5. 访问 WebUI 1. 创建虚拟环境 conda create -n sensevoice python3.11 -y conda activate sensevoice 2. 克隆代码 git clone https://github.com/FunAudioLLM/SenseVoic…

【Linux进阶】文件系统2——MBR和GPT

1.磁盘的分区 因为如果你的磁盘被划分成两个分区&#xff0c;那么每个分区的设备文件名是什么&#xff1f; 在了解这个问题之前&#xff0c;我们先来复习一下磁盘的组成&#xff0c;因为现今磁盘的划分与它物理的组成很有关系。 我们谈过磁盘主要由碟片、机械手臂、磁头与主轴马…

C++Windows环境搭建(CLion)

文章目录 CLion下载安装CLion下载CLion安装新建项目 CLion下载安装 CLion下载 打开网址&#xff1a;https://www.jetbrains.com/clion/download/ 点击Download进行下载。 CLion安装 双击下载好的安装包&#xff1a; 进入到安装页面&#xff0c;点击下一步&#xff1a; 选…

【粉丝福利 | 第8期】值得收藏!推荐10个好用的数据血缘工具

⛳️ 写在前面参与规则&#xff01;&#xff01;&#xff01; ✅参与方式&#xff1a;关注博主、点赞、收藏、评论&#xff0c;任意评论&#xff08;每人最多评论三次&#xff09; ⛳️本次送书1~4本【取决于阅读量&#xff0c;阅读量越多&#xff0c;送的越多】 目前市面上绝…

无人直播系统源码开发:功能~优势~开发方法

自动直播通常是指通过自动化技术来实现实时内容分发的过程&#xff0c;它结合了流媒体技术和人工智能&#xff08;如机器学习&#xff09;。以下是自动直播实现的基本步骤&#xff1a; 内容采集&#xff1a;通过摄像头、手机等设备捕捉实时画面&#xff0c;并通过编码将其转换成…

如何理解http与https协议,他们有什么区别?

写在前面的话&#xff0c;关于 HTTP 和 HTTPS 的问题&#xff0c;常常会被很多学习者忽略&#xff0c;HTTP、HTTPS 不就是网址的开头吗&#xff0c;有啥好了解的&#xff0c;浏览器的引擎实现了这个协议&#xff0c;在开发关系不大&#xff0c;但想要深入一些理解数据传输原理&…