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)

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

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

相关文章

“Install Js dependencies failed“JS SDK安装失败【Bug已解决-鸿蒙开发】

文章目录 项目场景:问题描述原因分析:解决方案:解决措施1解决方案2:其他解决方案解决方案3:此Bug解决方案总结项目场景: 在下载JS SDK时,出现下载失败的情况,并显示“Install Js dependencies failed”。 在使用版本为DevEco Studio 3.0.0.601 Beta1进行低代码开发时…

Echarts-使用渐变色填充

垂直方向的渐变 color: {type: linear,// x0,y1,柱子的颜色在垂直方向渐变x: 0,y: 1,colorStops: [// 0%处的颜色{offset: 0,color: #12c2e9,},// 50%处的颜色{offset: 0.5,color: #c471ed,},// 100%处的颜色{offset: 1,color: #f64f59,},],global: false // 缺省为 false} 水…

力扣347. 前 K 个高频元素(java,最小堆,快速排序法)

Problem: 347. 前 K 个高频元素 文章目录 前言题目描述思路解题方法复杂度Code 前言 对于求取Top K一般有如下两种题型&#xff1a; 1.针对静态数据&#xff08;查询TopK操作&#xff09; 2.针对动态数据&#xff08;包括添加数据操作和查询TOPK操作&#xff09; 一般解决思路…

第22章 NIO编程

在本章中需要掌握NIO中的缓冲区的作用&#xff0c;并理解缓冲区中的数据处理模型&#xff0c;掌握Channel的作用&#xff0c;并结合缓冲区实现数据I/O操作&#xff0c;理解文件锁的作用&#xff0c;并且掌握字符编码处理支持类的使用&#xff0c;掌握Reactor设计模型&#xff0…

Electron+Ts+Vue+Vite桌面应用系列:sqlite增删改查操作篇

文章目录 1️⃣ sqlite应用1.1 sqlite数据结构1.2 初始化数据库1.3 初始化实体类1.4 操作数据类1.5 页面调用 优质资源分享 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418 ElectronTsVueVite桌面应用系列 &#xff1a;这个系列包括了从桌…

【设计模式-2.2】创建型——简单工厂和工厂模式

说明&#xff1a;本文介绍设计模式中&#xff0c;创建型设计模式中的工厂模式&#xff1b; 飞机大战 创建型设计模式&#xff0c;关注于对象的创建&#xff0c;本文介绍的简单工厂和工厂模式同样也是。举一个游戏例子&#xff0c;如飞机大战游戏中&#xff0c;屏幕中敌人类型…

【开题报告】海洋多源数据质量控制应用服务的WebServer设计与实现

开 题 报 告 内 容 论文选题的意义、主要研究内容和文献资料调研情况 一、选题意义 在当今世界研究自然环境的大背景下&#xff0c;计算机技术与各学科、各领域的综合应用逐渐增多。作为地球上最广阔的水体&#xff0c;同时也是地球上决定气候发展的主要的因素之一&#xff0…

Unity学习笔记11

一、视频播放功能 1.如何让视频在游戏场景中播放&#xff1f; 在Assets目录下添加一个渲染器纹理&#xff0c;步骤&#xff1a;新建→渲染器纹理 首先在创建一个平面&#xff0c;想让视频在平面上显示。在平面上添加一个组件 Video Player 然后将视频文件拖拽到视频剪辑位置上…

自动化测试 —— requests和selenium模块!

一、requests基于POST请求 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #1.requests的GET与POST用法的区别&#xff1a; GET请求: (HTTP默认的请求方法就是GET) * 没有请求体 * 数据必须在1K之内&#xff01; * GET请求数据会暴露在浏览器…

【MyBatis】MyBatis操作数据库

目录 一&#xff0c;准备工作 1.1 创建工程 1.2 准备数据 1.3 数据库连接字符串 1.4 创建持久层接口UserInfoMapper 1.5 单元测试 二&#xff0c;注解的基础操作 2.1 打印日志 2.2 参数传递 2.3 增&#xff08;Insert&#xff09; 2.4 删&#xff08;Delete&#x…

pytest分布式执行(pytest-xdist)

前言 平常我们手工测试用例非常多时&#xff0c;比如有1千条用例&#xff0c;假设每个用例执行需要1分钟。如果一个测试人员执行需要1000分钟才能执行完&#xff0c;当项目非常紧急的时候&#xff0c;我们会用测试人力成本换取时间成本&#xff0c;这个时候多找个小伙伴把任务…

如何使用群晖Synology Office结合内网穿透实现多人远程编辑文件协同办公

使用群晖Synology Office提升生产力&#xff1a;多人同时编辑一个文件 文章目录 使用群晖Synology Office提升生产力&#xff1a;多人同时编辑一个文件本教程解决的问题是&#xff1a;1. 本地环境配置2. 制作本地分享链接3. 制作公网访问链接4. 公网ip地址访问您的分享相册5. 制…

react-route-dom 实现简单的嵌套路由

最终效果 点击 to test1 点击to test2 > to test21 点击to test2 > to test22 代码如下 path: "page",element: <父组件 />,children: [{ path: "test1", element: <Test1 /> },{path: "test2",element: <Test2 />…

【JavaEE初阶】死锁问题

目录 一、死锁的三种典型场景 1、一个线程&#xff0c;一把锁 2、两个线程&#xff0c;两把锁 3、N个线程&#xff0c;M把锁 死锁&#xff0c;是多线程代码中的一类经典问题。我们知道加锁是能解决线程安全问题的&#xff0c;但是如果加锁的方式不当&#xff0c;就可能产生死…

品味丰富美食,羊大师温暖心灵

品味丰富美食&#xff0c;羊大师温暖心灵 冬季来临&#xff0c;寒冷的天气让人们渴望寻找一种温暖和满足感&#xff0c;这时候美食便成了一种心灵享受。冬季与美食的结合&#xff0c;使得人们在寒冷的冬日也能感受到温暖与欢乐。本文小编羊大师将带大家领略冬季与美食的完美结…

PAT-10道题

PAT算法刷题 1002 1002 一&#xff1a;对于每一的1到6都进行枚举&#xff0c;进行递归操作 二&#xff1a;如果位数到了指定的n的时候&#xff0c;递归的条件&#xff0c;进行判断是否可以整除操作 #include<iostream> #include<algorithm> using namespace std; l…

c语言十进制转二进制

以下是一个将十进制数转换为二进制数的C语言代码示例&#xff1a; #include <stdio.h>void decimal_to_binary(int decimal) { int binary[32]; int i 0; while (decimal > 0) { binary[i] decimal % 2; decimal / 2; i; } pr…

zookeeper集群+kafka集群:

kafka3.0之前依赖于zookeeper。 zookeeper开源&#xff0c;分布式的架构。提供协调服务&#xff08;Apache项目&#xff09; 基于观察者模式涉及的分布式服务管理架构。 存储和管理数据。分布式节点上的服务接受观察者的注册。一旦分布式节点上的数据发生变化&#xff0c;由zoo…

工作时想摸鱼?不如背点单词冷静一下

今天给大家分享一款新发现的“摸鱼”神器「ToastFish」。 这个软件相当神奇&#xff0c;它可以让我们在用电脑时安全隐蔽地——背单词&#xff01; 是的&#xff0c;工作累了&#xff0c;打游戏乏了&#xff0c;背两个单词&#xff0c;既能放松&#xff0c;又能提高&#xff0c…

linux 之iptables

1.iptables防火墙基本介绍 Linux系统的防火墙&#xff1a;IP信息包过滤系统&#xff0c;它实际上由两个组件 netfilter和 iptables 组成。 主要工作在网络层&#xff0c;针对IP数据包。体现在对包内的IP地址、端口、协议等信息的处理上。 iptables由软件包iptables提供的命令…