C++ day38 动态规划 斐波那契数列 爬楼梯 使用最小花费爬楼梯

题目1:509 斐波那契数列

题目链接:斐波那契数列

对题目的理解

斐波那契数列由0和1开始,后面每一项数字(F(n))都是前两个数字的和,给一个n,计算F(n),(0<=n<=30)

动规五部曲

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

dp[i]:第i个斐波那契数的数值          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];中可以看出,dp[i]是依赖 dp[i - 1] 和 dp[i - 2],那么遍历的顺序一定是从前到后遍历

5)打印dp数组(debug)

伪代码

代码

class Solution {
public:int fib(int n) {if(n<=1) return n;vector<int> dp(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];}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

压缩版本(优化空间复杂度)

也可以发现,不使用dp数组,只维护3个数值也可以求解,最终的dp[1]是所求,sum也是所求

伪代码

代码

class Solution {
public:int fib(int n) {if(n<=1) return n;int dp[2];dp[0] = 0;dp[1] = 1;int sum= 0;for(int i=2;i<=n;i++){//控制循环的次数,计算多少次sum = dp[0]+dp[1];dp[0] = dp[1];dp[1] = sum;}return dp[1];//return sum;}
};

注意:如果代码写成这样,就会报错未定义变量sum

报的错误如下

错误的原因是

sum只在循环内可用,出了循环就无法访问了。需要将 sum 定义在循环外面,这样才能在函数末尾返回。

所以将代码修改为如下

class Solution {
public:int fib(int n) {if(n<=1) return n;int dp[2];dp[0] = 0;dp[1] = 1;int sum= 0;for(int i=2;i<=n;i++){//控制循环的次数,计算多少次sum = dp[0]+dp[1];dp[0] = dp[1];dp[1] = sum;}return dp[1];//return sum;}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

递归法

class Solution {
public:int fib(int n) {if(n<=1) return n;return fib(n-1)+fib(n-2);}
};
  • 时间复杂度:O(2^n)
  • 空间复杂度:O(n),算上了编程语言中实现递归的系统栈所占空间

题目2:70 爬楼梯

题目链接:爬楼梯

对题目的理解

楼梯爬n阶才能到达楼顶,每次可以爬1或2个台阶,有多少种不同的爬法(1<=n<=45)

本题其实就是求斐波那契数列

动规五部曲

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

dp[i]:达到第i阶有dp[i]种方法

2)确定递推公式

dp[i-1]再走1步到达dp[i]      dp[i-2]再走2步到达dp[i]

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

3)初始化递归数组

dp[0]=1;//达到第0阶有1种方法,含义上说不通,因为题目的n>=1,因此,初始化dp[0]没有意义

dp[0]=0;//没有走,没有用方法,这个可以,但是初始化dp[0]没有意义

只初始化dp[1]和dp[2],dp[1]=1,dp[2]=2,达到第1阶有1种方法,达到第2种有两种方法

4)确定遍历顺序

从前向后遍历,dp[i]依赖于前两个状态dp[i-1]和dp[i-2].

5)打印dp数组

代码

class Solution {
public:int climbStairs(int n) {if(n<=2) return n;vector<int>  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];}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

压缩版本(优化空间复杂度)

直接维护3个数即可

class Solution {
public:int climbStairs(int n) {if(n<=2) return n;int dp[3];dp[1]=1;dp[2]=2;for(int i=3;i<=n;i++){int sum = dp[1]+dp[2];dp[1] = dp[2];dp[2] = sum;}return dp[2];}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

扩展

本题还可以扩展,比如一步一个台阶,两个台阶,三个台阶,直到m个台阶,有多少种方法爬到n阶楼顶,这时,此题变成了一个完全背包问题

题目链接:扩展楼梯(完全背包)

题目3:746 使用最小花费爬楼梯

题目链接:使用最小花费爬楼梯

对题目的理解

整数数组cost中的元素cost[i]从楼梯第i个台阶向上爬需要支付的费用,每次只能爬一个或者两个台阶,可以选择,从下标为0或下标为1的台阶开始爬

返回到达楼顶的最低花费

!!!注意楼顶的位置是cost.size()

动规五部曲

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

dp[i]表示到达第i个台阶(第i个位置)所需要的最小花费是dp[i]

2)递推公式

可以从i-1往上跳1步到达i,此时dp[i] = dp[i-1]+cost[i-1],两者相加是因为从底层跳到i-1层还需要dp[i-1]的花费,然后从i-1跳到i,还需要cost[i-1]的花费

也可以从i-2往上跳2步到达i,此时dp[i] = dp[i-2]+cost[i-2],两者相加是因为从底层跳到i-2层还需要dp[i-2]的花费,然后从i-2跳到i,还需要cost[i-2]的花费

因此,递推公式为dp[i] = min(dp[i-1]+cost[i-1], dp[i-2]+cost[i-2])

3)dp数组初始化

dp[0] = 0,因为题目中说可以从下标为0的台阶开始爬,所需最小花费是0

dp[1] = 0,因为题目中说可以从下标为1的台阶开始爬,所需最小花费是0

4)遍历顺序

从前向后遍历,因为dp[i]由dp[i-1]dp[i-2]推出

5)打印dp数组(debug)

代码

class Solution {
public:int minCostClimbingStairs(vector<int>& cost) {vector<int> dp(cost.size()+1);//初始化dp数组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]);}return dp[cost.size()];}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

压缩版本(优化空间复杂度)

不使用dp数组了,直接使用3个数值即可(有点绕)

class Solution {
public:int minCostClimbingStairs(vector<int>& cost) {int dp[2];//初始化dp[0]=0;dp[1]=0;for(int i=2;i<=cost.size();i++){int minvalue = min(dp[1]+cost[i-1], dp[0]+cost[i-2]);dp[0] = dp[1];dp[1] = minvalue;}return dp[1];}
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于springBoot+mysql实现的竞赛管理系统

基于springBootmysql实现的竞赛管理系统&#xff0c;演示地址:系统登录 - 软件学院比赛管理系统 管理员账号&#xff1a;1&#xff0c;密码:1 包括比赛管理&#xff0c;队伍管理&#xff0c;教师管理&#xff0c;经费管理&#xff0c;学生管理&#xff0c;比赛结果&#xff0c;…

3D打印报价系统

一款3d打印报价系统不仅可以展示三维模型&#xff0c;还能自动计算模型的相关信息&#xff0c;如面积、体积和尺寸信息。 用户上传三维模型后&#xff0c;系统会自动为其生成一个报价页面。在这个页面上&#xff0c;用户可以看到他们模型的所有相关信息&#xff0c;包括面积、体…

Ubuntu 环境安装 Kafka、配置运行测试 Kafka 流程笔记

Kafka 介绍 Kafka 是一个由 Apache 软件基金会开发的开源流式处理平台。它被设计用于处理大规模数据流&#xff0c;提供高可靠性、高吞吐量和低延迟的消息传递系统。Kafka 可以用于构建实时数据管道和流式应用程序&#xff0c;让不同应用、系统或者数据源之间能够高效地进行数…

HCIA-H12-811题目解析(1)

1、【多选题】关于动态 MAC 地址表说法正确的是&#xff1f; A、通过报文中的源MAC地址学习获得的动态MAC表项会老化 B、通过查看指定动态MAC地址表项的个数&#xff0c;可以获取接口下通信的用户数 C、在设备重启后&#xff0c;之前的动态表项会丢失 D、在设备重启后&…

Alibaba微服务组件Nacos配置中心实战

Nacos 配置中心 配置中心作用 配置中心就是一种统一管理各种应用配置的基础服务组件。使得配置信息集中管理&#xff0c;易于维护&#xff0c;并且可以动态更新配置&#xff0c;使得分布式系统更加稳定可靠。 什么是Nacos配置中心 Nacos 提供用于存储配置和其他元数据的 ke…

奇异值分解SVD(Singular Value Decomposition)

一种理解方式&#xff0c;值得学习&#xff08;分解时空矩阵&#xff09; 先在这里阐述一下SVD的用途吧&#xff0c;具体细节稍后再做补充 1.通过SVD对数据的处理&#xff0c;我们可以使用小得多的数据集来表示原始数据集&#xff0c;这样做实际上是去除了噪声和冗余信息&…

re:Invent 2023 开发者指南来了!@开发者们,Let‘s 构!

开发者们看过来! 云计算领域的风向标、科技界的年度重磅盛会 2023 亚马逊云科技 re:Invent 将于 11 月 27 日在美国拉斯维加斯盛大启幕! 学习、互动、交流、比拼…… 作为世界开发者的年度技术狂欢盛宴 美国现场或国内互动将有哪些精彩环节? 开发者们&#xff0c;Lets …

java--方法重写

1.什么是方法重写 ①当子类觉得父类中的某个方法不好用&#xff0c;或者无法满足自己的需求时&#xff0c;子类可以重写一个方法名称、参数列表一样的方法&#xff0c;去覆盖父类的这个方法&#xff0c;这就是方法重写。 ②注意&#xff1a;重写后&#xff0c;方法的访问&…

【经济】-图文-30分钟普通人也能看懂经济如何运行

写在前面 最近看了一个关于宏观经济的视频&#xff0c;经济机器是如何运行的&#xff0c;视频的作者是Ray Dalio&#xff08;雷达利奥&#xff09;&#xff0c;发表于2017年&#xff0c;视频时长30分钟&#xff0c;小动画做的很棒。看完视频后&#xff0c;觉得挺有意思的&#…

Java小游戏 王者荣耀

GameFrame类 所需图片&#xff1a; package 王者荣耀;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.util.ArrayLis…

【实验】配置用户通过IPv6方式上网

【赠送】IT技术视频教程&#xff0c;白拿不谢&#xff01;思科、华为、红帽、数据库、云计算等等https://xmws-it.blog.csdn.net/article/details/117297837?spm1001.2014.3001.5502【微/信/公/众/号&#xff1a;厦门微思网络】 组网需求 运营商为企业分配了WAN侧的IPv6地址11…

工业以太网交换机有哪些优点?

工业以太网交换机是一种常见的网络设备&#xff0c;具备工业级特性。在轨道交通、智能制造以及工业自动化控制系统中扮演着重要的角色。随着工业自动化水平不断进步&#xff0c;对工业以太网交换机的要求也日益提高。 工业以太网交换机的工作原理 工业以太网交换机与多种工业…