【算法篇】逐步理解动态规划1(斐波那契数列模型)

目录

斐波那契数列模型  

1. 第N个泰波那契数

 2.使用最小花费爬楼梯

3.解码方法 


         学过算法的应该知道,动态规划一直都是一个非常难的模块,无论是状态转移方程的定义还是dp表的填表,都非常难找到思路。在这个算法的支线专题中我会结合很多力扣题型,由简单到复杂,带大家深度剖析动态规划类的题型,欢迎大家关注啊。

顺序:

题目链接-》算法思路-》代码呈现

斐波那契数列模型  

动态规划类题目解题步骤:

  1. 依据题目进行状态表示(dp[i]的含义)
  2. 写出状态转移方程(类似于dp[i]=dp[i-1]+dp[i-2])
  3. 为防止填表时数组越界,对dp表进行初始化(dp[0]=dp[1]=1)
  4. 搞清楚填表顺序(从前往后或者从后往前)
  5. 利用dp表返回问题答案

1. 第N个泰波那契数

题目链接:

https://leetcode.cn/problems/n-th-tribonacci-number/description/

算法思路:

1. 状态表⽰:
这道题可以「根据题⽬的要求」直接定义出状态表⽰:
dp[i] 表⽰:第 i 个泰波那契数的值。
2. 状态转移⽅程:
题⽬已经⾮常贴⼼的告诉我们了:
dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]
3. 初始化:
从我们的递推公式可以看出, dp[i] i = 0 以及 i = 1 的时候是没有办法进⾏推导的,因为 dp[-2] dp[-1] 不是⼀个有效的数据。因此我们需要在填表之前,将 0, 1, 2 位置的值初始化。题⽬中已经告诉我们 dp[0] = 0,dp[1] = dp[2] = 1 。
4. 填表顺序:
毫⽆疑问是「从左往右」。
5. 返回值:
应该返回 dp[n] 的值。

代码呈现:

class Solution {
    public int tribonacci(int n) {
        if(n==0){
            return 0;
        }
        if(n==1||n==2){
            return 1;
        }
      int[] dp=new int[n+1];
      dp[0]=0;
      dp[1]=1;
      dp[2]=1;
      for(int i=3;i<=n;i++){
        dp[i]=dp[i-1]+dp[i-2]+dp[i-3];
      }
      return dp[n];
    }
}

 2.使用最小花费爬楼梯

题目链接:

https://leetcode.cn/problems/min-cost-climbing-stairs/description/

算法思路:

1. 状态表⽰:
这道题可以根据「经验 + 题⽬要求」直接定义出状态表⽰:
dp[i] 表⽰:到达 i 位置时的最⼩花费。(注意:到达 i 位置的时候, i 位置的钱不需要算上)
2. 状态转移⽅程:
根据最近的⼀步,分情况讨论:
  • 先到达 i - 1 的位置,然后⽀付 cost[i - 1] ,接下来⾛⼀步⾛到 i 位置: dp[i - 1] + csot[i - 1]
  • 先到达 i - 2 的位置,然后⽀付 cost[i - 2] ,接下来⾛⼀步⾛到 i 位置: dp[i - 2] + csot[i - 2]
3. 初始化:
从我们的递推公式可以看出,我们需要先初始化 i = 0 ,以及 i = 1 位置的值。容易得到dp[0] = dp[1] = 0 ,因为不需要任何花费,就可以直接站在第 0 层和第 1 层上。
4. 填表顺序:
根据「状态转移⽅程」可得,遍历的顺序是「从左往右」。
5. 返回值:
根据「状态表⽰以及题⽬要求」,需要返回 dp[n] 位置的值。

代码呈现:

class Solution {
    public int minCostClimbingStairs(int[] cost) {
      int size=cost.length;
      if(size==2) return Math.min(cost[0],cost[1]);
      int[] dp=new int[size+1];
       dp[0]=0;
       dp[1]=0;
       dp[2]=Math.min(cost[0],cost[1]);
       for(int i=3;i<=size;i++){
           dp[i]=Math.min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);
       }
       return dp[size];
    }
}

3.解码方法 

题目链接:

https://leetcode.cn/problems/decode-ways/

 算法思路:

类似于斐波那契数列
1. 状态表⽰:
根据以往的经验,对于⼤多数线性 dp ,我们经验上都是「以某个位置结束或者开始」做⽂章,这
⾥我们继续尝试「⽤ i 位置为结尾」结合「题⽬要求」来定义状态表⽰。
dp[i] 表⽰:字符串中 [0 i] 区间上,⼀共有多少种编码⽅法。
2. 状态转移⽅程:
定义好状态表⽰,我们就可以分析 i 位置的 dp 值,如何由「前⾯」或者「后⾯」的信息推导出
来。
关于 i 位置的编码状况,我们可以分为下⾯两种情况:
i. i 位置上的数单独解码成⼀个字⺟;
ii. i 位置上的数与 i - 1 位置上的数结合,解码成⼀个字⺟。
下⾯我们就上⾯的两种解码情况,继续分析:
  • i 位置上的数与 i - 1 位置上的数结合在⼀起,解码成⼀个字⺟,也存在「解码成功」和「解码失败」两种情况:

i. 解码成功:当结合的数在 [10, 26] 之间的时候,说明 [i - 1, i] 两个位置是可以解码成功的,那么此时 [0, i] 区间上的解码⽅法应该等于 [0, i - 2 ] 区间上的解码⽅法,原因同上。此时 dp[i] = dp[i - 2]

ii. 解码失败:当结合的数在 [0, 9] [27 , 99] 之间的时候,说明两个位置结合后解码失败(这⾥⼀定要注意 00 01 02 03 04 ...... 这⼏种情况),那么此时 [0, i] 间上的解码⽅法就不存在了,原因依旧同上。此时 dp[i] = 0

  • 让 i 位置上的数单独解码成⼀个字⺟,就存在「解码成功」和「解码失败」两种情况:

i. 解码成功:当 i 位置上的数在 [1, 9] 之间的时候,说明 i 位置上的数是可以单独解 码的,那么此时 [0, i] 区间上的解码⽅法应该等于 [0, i - 1] 区间上的解码⽅ 法。因为 [0, i - 1] 区间上的所有解码结果,后⾯填上⼀个 i 位置解码后的字⺟就 可以了。此时 dp[i] = dp[i - 1]

ii. 解码失败:当 i 位置上的数是 0 的时候,说明 i 位置上的数是不能单独解码的,那么此时 [0, i] 区间上不存在解码⽅法。因为 i 位置如果单独参与解码,但是解码失败了,那么前⾯做的努⼒就全部⽩费了。此时 dp[i] = 0

3. 初始化:
⽅法⼀(直接初始化):
由于可能要⽤到 i - 1 以及 i - 2 位置上的 dp 值,因此要先初始化「前两个位置」。
初始化 dp[0]
i. s[0] == '0' 时,没有编码⽅法,结果 dp[0] = 0
ii. s[0] != '0' 时,能编码成功, dp[0] = 1
初始化 dp[1]
i. s[1] [1 9] 之间时,能单独编码,此时 dp[1] += dp[0] (原因同上,
dp[1] 默认为 0
ii. s[0] s[1] 结合后的数在 [10, 26] 之间时,说明在前两个字符中,⼜有⼀种
编码⽅式,此时 dp[1] += 1
⽅法⼆(添加辅助位置初始化):
可以在最前⾯加上⼀个辅助结点,帮助我们初始化。使⽤这种技巧要注意两个点:
i. 辅助结点⾥⾯的值要保证后续填表是正确的;
ii. 下标的映射关系
4. 填表顺序:
毫⽆疑问是「从左往右」
5. 返回值:
应该返回 dp[n - 1] 的值,表⽰在 [0, n - 1] 区间上的编码⽅法。

代码呈现:

class Solution {
    public int numDecodings(String s) {
       char[] arr=s.toCharArray();
       int n=arr.length;
       int[] dp=new int[n+1];
       dp[0]=1;
       if(arr[0]=='0') dp[1]=0;
       else dp[1]=1;
       if(n==1){
        return dp[1];
       }
       for(int i=2;i<n+1;i++){
        if(arr[i-1]!='0'){
                dp[i]+=dp[i-1];
        }
        if(((arr[i-2]-'0')*10+(arr[i-1]-'0'))<=26&&((arr[i-2]-'0')*10+(arr[i-1]-'0'))>=10){
                dp[i]+=dp[i-2];
            }
       }
       return dp[n];
    }
}

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

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

相关文章

Java学习笔记 | Java基础语法 | 03 | 流程控制语句

文章目录 0 前言1.流程控制语句1.1 流程控制语句分类1.2 顺序结构 2.判断语句2.1 if语句1. if语句格式1练习1&#xff1a;老丈人选女婿练习2&#xff1a;考试奖励 2. if语句格式2练习1&#xff1a;吃饭练习2&#xff1a;影院选座 3. if语句格式3练习1&#xff1a;考试奖励 2.2 …

Vue使用font-face自定义字体详解

目录 1 介绍2 使用2.1 语法2.2 属性说明2.3 Vue使用案例2.3.1 全局定义字体2.3.2 在页面使用 3 注意事项 1 介绍 font-face 是 CSS 中的一个规则&#xff0c;它允许你加载服务器上的字体文件&#xff08;远程或者本地&#xff09;&#xff0c;并在网页中使用这些字体。这样&am…

使用 STL 容器发生异常的常见原因分析与总结

目录 1、概述 2、使用STL列表中的元素越界 3、遍历STL列表删除元素时对迭代器自加处理有问题引发越界 4、更隐蔽的遍历STL列表删除元素时引发越界的场景 5、多线程同时操作STL列表时没有加锁导致冲突 6、对包含STL列表对象的结构体进行memset操作导致STL列表对象内存出异…

大学教材《C语言程序设计》(浙大版)课后习题解析 | 第一、二章

概述 本文主要提供《C语言程序设计》(浙大版) 第一、二章课后习题解析&#xff0c;以方便同学们完成题目后作为参考对照。后续将写出三、四章节课后习题解析&#xff0c;如想了解更多&#xff0c;请持续关注该专栏。 专栏直达链接&#xff1a;《C语言程序设计》(浙大版)_孟俊宇…

Hive SQL必刷练习题:复购率问题(*****)

是说这个数据表中&#xff0c;找到最后一天 &#xff0c;也就是今天的日期&#xff0c;max(date) over()S today 【借助开窗函数】 截至最后一天位置&#xff0c;也就是“今天“&#xff0c;表中的最新的一天 去看90天内“某商品复购率 近90天内购买它至少两次的人数 购买它…

c++常考基础知识(2)

二.c关键字 关键字汇总 c中共有63个关键字&#xff0c;其中包括int&#xff0c;char&#xff0c;double等类型关键字&#xff0c;if&#xff0c;else&#xff0c;while&#xff0c;do&#xff0c;等语法关键字&#xff0c;还有sizeof等函数关键字。 三.数据结构 1.数组&#x…

常见的OOM 问题的 6 种场景

今天跟大家一起聊聊线上服务出现 OOM 问题的 6 种场景,希望对你会有所帮助。 一、堆内存 OOM 堆内存 OOM 是最常见的 OOM 了。 出现堆内存 OOM 问题的异常信息如下: java.lang.OutOfMemoryError: Java heap space此 OOM 是由于 JVM 中 heap 的最大值,已经不能满足需求了…

Git的原理和使用(四)

目录 远程操作 理解分布式版本控制系统 远程仓库 新建远程仓库 克隆远程仓库 向远程仓库推送 拉取远程仓库 配置Git 忽略特殊文件 为命令配置别名 标签管理 理解标签 创建标签 操作标签 远程操作 理解分布式版本控制系统 1、每个人的电脑上都是一个完整的版本库…

批量重命名文件名,批量管理文件,复制后轻松删除原文件

在现代工作中&#xff0c;我们经常需要处理大量的文件&#xff0c;无论是工作文档、图片还是视频资料。对于很多人来说&#xff0c;文件管理是一项繁琐且耗时的任务。不过&#xff0c;现在有一种高效的文件管理方法&#xff0c;可以帮助你轻松复制文件后删除原文件夹&#xff0…

2024.03.24 exam

2024.03.24 exam 据说是事业单位考试例题&#xff0c;娱乐一下脑子

zabbix安装及使用(错误及解决方案)

安装zabbix 常见错误&#xff1a; Zabbix下载错误 6.0与5.0版本冲突 解决方法 yum -y install zabbix-server-mysql zabbix-web-mysql zabbix-get --skip-broken zabbix6.0-web 自己有数据库&#xff0c;使用以下命令 pid找不到 /var/log/zabbix/zabbix_server.log 错误&a…

Docker Command

小试牛刀 # 查看docker版本 docker -v docker --version # 查看帮助 docker --help # 永远的Hello World docker run hello-world镜像操作 查看本地已有的镜像 docker images -a :列出本地所有的镜像&#xff08;含中间映像层&#xff09; -q :只显示镜像ID --digests :显示…

尝试Docker Dev Environments

无法从本地目录创建容器环境 创建的容器环境无法在VS Code打开 从官方仓库打开 结果vscode报错。fine&#xff0c;告辞。老老实实用本地环境开发。

为什么LLM都在卷上下文长度?不是其他卷不起,而是上下文更有性价比!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

深度学习pytorch——2D函数优化实例(持续更新)

课程&#xff1a;课时46 优化问题实战_哔哩哔哩_bilibili 这就是我们今天要求的2D函数&#xff1a; 下图是使用python绘制出来的图像&#xff1a; 但是可以看出有4个最小值&#xff0c;但是还是不够直观&#xff0c;还是看课程里面给的比较好&#xff0c;蓝色是最低点位置&am…

哲学♂家带你用动态内存函数实现二维数组

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、思路分析 二、实现 总结 前言 最近在做题的时候发现一个比较考验技术的问题&#xff0c;用内存函数模拟实现二维数组&#xff0c;接下来给大家演示一下我的做…

20240318-2-推荐算法Graph_Embedding

Graph Embedding 在许多推荐场景下&#xff0c;可以用网络结构数据来刻画对象&#xff08;用户、商品等&#xff09;之间的关系。例如&#xff1a;可以将用户和商品作为网络中的结点&#xff0c;用户和商品之间的边代表购买关系。 Graph Embedding 是一种将网络中对象之间的关…

python项目格式代码风格

Visual Studio Code 选择使用 black 作为代码格式化工具&#xff0c;保证提交代码风格的统一 1. Install black pip install black2. Install black and isort extension for vscode: 3. 设定black及isort的格式化配置 3.1. ctrl , 打开配置面板 3.2. 在弹出的json配置中添…

域名防红源码-再次启用已经红掉拦截的域名-提示跳转浏览器打开

比如说你的域名已经红掉了被拦截了&#xff0c;还想继续在使用&#xff0c;那么你用这个系统后呢&#xff0c;他就会提示跳转浏览器打开。以此达到再次启用的效果。 假如你的域名是A&#xff0c;已经红掉的&#xff1b;使用此方法新加一个域名B&#xff1b;之后你每次发域名B或…

【理解机器学习算法】之Clustering算法(K-Means)

实现 K-means 聚类从零开始涉及几个关键步骤&#xff1a;初始化质心、将点分配给最近的质心、根据分配更新质心&#xff0c;以及重复这个过程直到收敛。这里是一个基本的 Python 实现&#xff1a; K-means 算法步骤&#xff1a; 初始化质心&#xff1a;从数据点中随机选择 k …