动态规划01 三步问题[C++]

  ​​​​​​

图源:文心一言

上机题目练习整理,本篇作为动态规划的代码,因为做题入门很少找到带图的讲解(难道是因为太简单,所以没有人嘛),所以干脆自己写一份,供小伙伴们参考~🥝🥝

  • 第1版:在力扣新手村刷题的记录~🧩🧩

编辑:梅头脑🌸

审核:文心一言

题目:面试题 08.01. 三步问题 - 力扣(LeetCode)


🧵面试题 08.01. 三步问题

🧩题目

三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。

示例1:

 输入:n = 3 
 输出:4
 说明: 有四种走法

示例2:

 输入:n = 5
 输出:13

提示:

  1. n范围在[1, 1000000]之间

🌰解题1:数组存放

📇算法思路

  • 算法思想:
    •  由于每一步我们可以选择走1步、2步或3步,并且只能向右走,因此我们可以将问题分解为更小的子问题:到达位置 i 的方式数可以通过到达位置 i-1i-2 和 i-3 的方式数来推导。这样,我们就可以使用动态规划来逐步构建到达每个位置的方式数,直到到达目标位置 n;
    • 算法的关键在于正确地定义状态(在这里是 dp[i])和状态转移方程(在这里是 dp[i] = dp[i-1] + dp[i-2] + dp[i-3],但需要注意边界条件,确保不会访问数组的负索引)。
  • 时间复杂度:O(n),n是需要到达的目标位置,使用了1个循环,遍历步数i(从1到n);
  • 空间复杂度:O(n),代码使用了一个一维数组dp来存储到达每个位置的方式数;

⌨️算法代码

#include <iostream>  
#include <vector>  
using namespace std;  

const int MOD = 1000000007; // 取模的大质数  
  
class Solution {  
public:  
    int waysToStep(int n) {
        vector<int> dp(n + 1, 0); // 一维数组,dp[i] 表示到达位置 i 的方式数  
        dp[0] = 1; // 初始条件,到达位置 0 的方式数为 1  

        for (int i = 1; i <= n; i++) {
            // 遍历到达位置 i 的所有可能的前一步位置  
            for (int j = 1; j <= 3 && i - j >= 0; j++) {
                dp[i] += dp[i - j] % MOD; ; // 累加从各个前一步位置到达位置 i 的方式数,并取模  
            }
        
        // 输出测试
        // cout << "dp after step " << i << ": ";
        // for (int k = 0; k <= i; k++) {
        //    cout << dp[k] << " ";
        // }
        // cout << endl;
    }

        return dp[n]; // 返回到达位置 n 的方式数  
    }
};
/*  
int main() {  
    Solution solution;  
    int a = solution.waysToStep(3);  
    cout << "Number of ways to step to position 3: " << a << endl;  
    return 0;  
}
*/

 作者:文心一言

📇代码解释

1:状态方程

  • 小孩走向第 i 级台阶的位置可以是:
    • 从第 i−1 阶迈 1 阶;
    • 从第 i−2 阶迈 2 阶;
    • 从第 i−3 阶迈 3 阶;
  • 那么状态方程可以是:
    • dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3];代码等价的表示为:for (int j = 1; j <= 3 && i - j >= 0; j++) { dp[i] += dp[i - j] };
    • 根据题目要求,为了避免整数溢出问题,确保结果在计算机的整数表示范围内,执行取余操作,而1000000007这是一个常见的大质数,因此算式:dp[i] = (dp[i] + dp[i - j]) % MOD; 
  • 初始状态:第0个台阶有1种方式(不动);
  • i 的范围:从1走向n级台阶;

2:算法模拟 

注意,动态数组就是一种记忆的工具,它可以记录到达 i-1 、i-1、i-3的跳法,因此计算 i 时仅用 i 的前3轮的跳法相加即可;

举个栗子,例如跳到台阶3,它有4种方法到达:

  • 1次跳3级,从0级台阶跳到3级台阶;而跳到dp[0]仅1种跳法,在第2轮的dp[0]中记录,因此dp[0]→dp[3]也是唯一跳法;
  • 1次跳2级,从1级台阶跳到3级台阶;而dp[0]跳到dp[1]仅1种跳法,在第2轮的dp[1]中记录,因此dp[1]→dp[3]也是唯一跳法;
  • 1次跳1级,从2级台阶跳到3级台阶;而dp[0]跳到dp[2]有2种跳法,在第2轮的dp[2]中记录,因此dp[2]→dp[3]也是2种跳法;
  • 相加,dp[0] + dp[1] + dp[2] = 4,即为4种台阶跳法~~
轮数 / 跳法dp[0]dp[1]dp[2]dp[3]备注
初始1
第1轮111:dp[0]→dp[1]
第2轮112

1:dp[0]→dp[1]→dp[2]

2:dp[0]→dp[2]

第3轮1124

1:dp[0]→dp[1]→dp[3]

2:dp[0]→dp[1]→dp[2]→dp[3]

3:dp[0]→dp[2]→dp[3]

4:dp[0]→dp[3]

🌰解题2:变量存放

⌨️算法代码

class Solution {
public:
    int waysToStep(int n) {
        if(n<3) return n;      // 跳到台阶1有1种方法,跳到台阶2有2种方法
        int base=1e9+7;        // 取模质数
        int dp0=1,dp1=2,dp2=4; // 初始化3种状态:跳到台阶dp0有1种方式,跳到台阶dp1有2种方式,跳到台阶dp2有3种方式
        int temp1,temp2;       // 记录 dp[i-1],dp[i-2]
        while(n--!=3){         // 台阶数n不等于3时,执行循环,并且n-1
            temp1=dp1,temp2=dp2;             // 使用temp1和temp2保存dp1和dp2的值,因为dp1和dp2即将被更新 
            dp2=((dp0+dp1)%base+dp2)%base;   // 走到第n个台阶的方法数等于走到第n-1, n-2, n-3个台阶的方法数之和
            dp0=temp1,dp1=temp2;             // 更新dp0和dp1为上一轮的dp1和dp2  
        }
        return dp2;            // 循环结束后,dp2中存储的就是走到第n个台阶的方法数  
    }
};

作者:treasure_
链接:https://leetcode.cn/problems/three-steps-problem-lcci/solutions/529898/c-dong-tai-gui-hua-by-treasure_-611d/

  • 时间复杂度:O(n),n是需要到达的目标位置,使用了1个循环,遍历步数i(从1到n);
  • 空间复杂度:O(1),不同于方法一使用数组,方法二使用了3个常数存放状态,只要更新temp1、temp2、dp2、dp0,就可以实现状态方程dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]的功能;
  • 备注:
    • 算法代码1、2在思路上非常相似,只是语法的细节有些不同;
    • 算法2我已经逐行注释在了旁边,算法思路不再赘述【emm...如果真的需要再详细解说1遍,欢迎小伙伴在评论区留言】。

🔚结语

博文到此结束,写得模糊或者有误之处,欢迎小伙伴留言讨论与批评,督促博主优化内容{例如有错误、难理解、不简洁、缺功能}等,博主会顶锅前来修改~~😶‍🌫️😶‍🌫️

我是梅头脑,本片博文若有帮助,欢迎小伙伴动动可爱的小手默默给个赞支持一下,感谢点赞小伙伴对于博主的支持~~🌟🌟

同系列的博文:🌸动态规划_梅头脑_的博客-CSDN博客

同博主的博文:🌸随笔03 笔记整理-CSDN博客

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

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

相关文章

CSS的动画

CSS的动画 在本节&#xff0c;我们将学习keyframes动画。 1. 动画的基本使用 1. 定义动画 定义动画有两种写法&#xff1a; 简单定义方式 keyframes 动画名 {/* from代表初始状态 */from {/*property1:value1*/transform: translate(0%);}/* to代表结束状态 */to {transfor…

Win32 SDK Gui编程系列之--弹出式菜单

1.弹出式菜单 例如,在命令提示窗口中点击鼠标右键,会出现如下图所示的弹出菜单(下拉菜单)。 这种弹出式菜单的实现很简单。不创建菜单栏,用CreatePopupMenu函数创建的菜单是最顶端的菜单就可以了。 菜单的显示使用TrackPopupMenu函数进行。 例如,点击鼠标右键显示弹出…

JAVA装饰器模式详解

装饰器模式 1 装饰器模式介绍 装饰模式(decorator pattern) 的原始定义是&#xff1a;动态的给一个对象添加一些额外的职责. 就扩展功能而言,装饰器模式提供了一种比使用子类更加灵活的替代方案. 假设现在有有一块蛋糕,如果只有涂上奶油那这个蛋糕就是普通的奶油蛋糕, 这时如…

[职场] 智能材料与结构专业的就业前景 #经验分享#学习方法

智能材料与结构专业的就业前景 智能材料与结构专业是面向国家智能制造强国战略&#xff0c;面向地方经济新旧动能转换需求&#xff0c;学习智能材料与结构的基础理论及基本知识&#xff0c;接受智能材料制备、组织分析、性能测试、智能材料系统集成技能的基本训练&#xff0c;…

蓝桥杯省赛无忧 课件127 线段树维护哈希

01 问题引入 02 算法思路 03 代码实现 04 例题讲解

Linux中共享内存(mmap函数的使用)

内存映射的基本使用 内存映射 概念&#xff1a; 使一个磁盘文件与内存中的一个缓冲区相映射&#xff0c;进程可以像访问普通内存一样对文件进行访问&#xff0c;不必再调用read,write。 mmap()的优点&#xff1a; 实现了用户空间和内核空间的高效交互方式 优化前&#xff1a;优…

时序数据库Influxdb查询多个字段_field同一时间的值,组成一条数据

Influxdb将表格数据多个字段_field从垂直列布局聚合成水平布局行字段。 问题 1、Influxdb 是一种时间序列数据库&#xff0c;在我的项目中主要用来存储换热站的测点数据的。换热站有非常多的测点&#xff0c;我们用Flux 语法去查询测点数据&#xff0c;返回的数据结构是每个测…

【MySQL进阶之路】MySQL生产环境部署该如何选择机器配置?

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

酷开科技,打造非凡的生活体验

酷开科技&#xff0c;作为一家专注于智能电视操作系统研发及智能电视运营增值服务的高科技企业&#xff0c;始终致力于为消费者提供非凡的生活体验。通过不断创新的技术和产品&#xff0c;酷开科技为消费者们带来了便捷、舒适、个性化的智能生活。 首先&#xff0c;酷开科技在智…

阿里云游戏服务器收费价格表,一年和1个月报价

阿里云游戏服务器租用价格表&#xff1a;4核16G服务器26元1个月、146元半年&#xff0c;游戏专业服务器8核32G配置90元一个月、271元3个月&#xff0c;阿里云服务器网aliyunfuwuqi.com分享阿里云游戏专用服务器详细配置和精准报价&#xff1a; 阿里云游戏服务器租用价格表 阿…

【 buuctf-数据包中的线索】

这题比较简单&#xff0c;只要能想到base64 转图片 复制此处密文&#xff0c;发现 base64 正常解码解不出来&#xff0c;就要想到可能是图片 需要注意&#xff0c;/9j是jpg文件头的 base64 编码 BUUCTF的wireshark流量分析题目writeup汇总_ctf wireshark练习题-CSDN博客&#…

蓝桥杯刷题day07——斐波那契与7

1、题目描述 斐波那契数列的递推公式为:FnFn-1Fn-2, 其中F1F21. 请问, 斐波那契数列的第 1 至 202202011200 项&#xff08;含&#xff09;中, 有多少项的个位 是 7 。 答案提交 这是一道结果填空的题, 你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填…

Maven构建OSGI+HttpServer应用

Maven构建OSGIHttpServer应用 官网&#xff08;https://eclipse.dev/equinox/server/http_in_equinox.php&#xff09;介绍有两种方式&#xff1a; 一种是基于”org.eclipse.equinox.http”包的轻量级实现&#xff0c;另一种是基于”org.eclipse.equinox.http.jetty”包&#…

2024最新CleanMyMac X优化Mac电脑系统体验分享

使用Mac电脑的用户都希望它们能够保持最佳性能。但有时&#xff0c;你可能会发现你的Mac运行变慢或响应迟缓。这可能是由于几个原因造成的&#xff0c;包括硬盘空间不足、系统缓存堆积、以及过多的启动项等。解决了这些问题&#xff0c;你可以显著提升你的Mac性能。本文将探讨导…

工程示例(LED、流水灯、蜂鸣器)

LED闪烁 #include "stm32f10x.h" // Device header #include "Delay.h"int main(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitSructure;GPIO_InitSructure.GPIO_Mode GPIO_Mode_Out_PP;GPIO…

SpringBoot+随机盐值+双重MD5实现加密登录

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 前言一、salt…

遗失的源代码之回归之路的探索与实践

背景 最近比较突然被安排接手一个项目,该项目的情况如下 原生和RN结合的混合开发模式组件化开发,有很多基础组件以及业务组件但是在梳理项目依赖时发现了个别组件源码不全的情况,于是写了个cli用于对比两个版本产物文件,生成差异结果以便于快速进行源码找回恢复。 结果如下…

Python tkinter (16) —— Progressbar

本文主要介绍Python tkinter 进度条Progressbar应用及示例。 目录 系列文章 进度条Progressbar 基本概念 参数&#xff1a; mode参数 基本应用 动画设计 引入time 具体实现 start/step/stop step(amount)&#xff1a; start(interval)&#xff1a; stop()&#xff…

QT 范例阅读:系统托盘 The System Tray Icon example

main.cpp QApplication app(argc, argv);//判断系统是否支持 系统托盘功能if (!QSystemTrayIcon::isSystemTrayAvailable()) {QMessageBox::critical(0, QObject::tr("Systray"),QObject::tr("I couldnt detect any system tray ""on this system.&qu…

一文掌握SpringBoot注解之@Configuration知识文集(6)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…