【动态规划】:泰波那契模型_解码方法

朋友们、伙计们,我们又见面了,本专栏是关于各种算法的解析,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

C 语 言 专 栏:C语言:从入门到精通

数据结构专栏:数据结构

个  人  主  页 :stackY、

C + + 专 栏   :C++

Linux 专 栏  :Linux

目录

1. 题目解析

2. 算法原理

2.1 状态表示

2.2 状态转移方程

2.3 初始化

2.4 填表顺序

2.5 返回值

3. 代码实现

4. 算法复杂度 

5. 优化边界情况以及初始化 

5.1 优化之后代码 


1. 题目解析

Leetcode91.解码方法:https://leetcode.cn/problems/decode-ways/description/

一条包含字母 A-Z 的消息通过以下映射进行了 编码 :

'A' -> "1"
'B' -> "2"
...
'Z' -> "26"

要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,"11106" 可以映射为:

  • "AAJF" ,将消息分组为 (1 1 10 6)
  • "KJF" ,将消息分组为 (11 10 6)

注意,消息不能分组为  (1 11 06) ,因为 "06" 不能映射为 "F" ,这是由于 "6" 和 "06" 在映射中并不等价。

给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。

题目数据保证答案肯定是一个 32 位 的整数。

示例 1:

输入:s = "12"
输出:2
解释:它可以解码为 "AB"(1 2)或者 "L"(12)。

示例 2:

输入:s = "226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。

示例 3:

输入:s = "06"
输出:0
解释:"06" 无法映射到 "F" ,因为存在前导零("6" 和 "06" 并不等价)。

提示:

  • 1 <= s.length <= 100
  • s 只包含数字,并且可能包含前导零。

本题采用动态规划的思想,以某一位置为开始,或者以某一位置为结束,要注意的是:

例如:

06没有解码方式,因为单独的0不能解码,并且06组合起来也不能解码,06和6并不等价。

60也没有解码方式,6单独有解码方式,但是0没有,并且二者结合60也没有解码方式。 

262有两种解码方式,依次单独解码(1),26组合解码(2),但是62组合没有解码方式。

那么就表明:

一个数要能单独解码就要在'1' ~ '9' 之间

两个数组合一起能解码就要在'10' ~ '26' 之间

2. 算法原理

2.1 状态表示

根据题目要求:

要求的是总共的解码数,那么假设一共有i个数

那么我们以i位置为结尾时,所得的解码的方法就是要求的解码方法总数。

因此:dp[i] 就表示解码的方法数。

2.2 状态转移方程

根据最近的一步划分问题:

dp[i]位置的解码数就是:①s[i]单独解码数

                                       ②s[i-1]和s[i]组合起来的解码数

①如果s[i]能单独解码,那么此时的解码数就是dp[i-1]时的解码数,如果不能单独解码,那么之前的工作都作废了,总的解码数为0的。

②如果s[i-1]和s[i]组合起来能解码,那么此时的解码数就是dp[i-2]时的解码数,如果组合起来不能解码,那么就为0。

因此如果两种方式都可以解码成功:dp[i] = dp[i-1] + dp[i-2]

2.3 初始化

为了防止越界,求dp[i]就要知道dp[i-1]和dp[i-2],所以需要将dp[0]和dp[1]初始化

dp[0]就是s[0]位置的解码数,那么只有0和1两种情况,如果s[0]能单独解码,就是1,不能则是0。

dp[1]就是s[1]位置的解码数,这里存在两种情况,如果s[0]和s[1]能单独解码就算一种,如果s[0]和s[1]组合起来能解码也是一种,如果s[1]单独都不能解码就是0。

因此dp[1]的解码方法是0或1或2。

2.4 填表顺序

从左向右

2.5 返回值

dp[n-1]

3. 代码实现

class Solution 
{
public:
    int numDecodings(string s) 
    {
        int n = s.size();
        // 1. 创建dp表
        vector<int> dp(n);   

        // 2. 初始化
        dp[0] = s[0] != '0';
        // 边界情况
        if(n == 1) return dp[0];

        if(s[0] != '0' && s[1] != '0') dp[1] += 1;
        int ret = (s[0] - '0')*10 + s[1] - '0';
        if(ret >= 10 && ret <= 26) dp[1] += 1;
        
        // 3. 填表
        for(int i = 2; i<n; i++)
        {
            // 单独解码
            if(s[i] != '0') dp[i] += dp[i-1];
            int ret = (s[i-1] - '0')*10 + s[i] - '0';
            // 组合解码
            if(ret >= 10 && ret <= 26) dp[i] += dp[i-2];
        }

        // 4. 返回值
        return dp[n-1];
    }
};

4. 算法复杂度 

时间复杂度:O(N)

空间复杂度:O(N)

5. 优化边界情况以及初始化 

通过上面的代码可以发现: 初始化部分与填表部分逻辑类似代码冗余,所以可以做以优化

我们在创建dp表时可以多创建一个空间,只需要对这个空间进初始化就可以优化繁琐的初始化过程:

既然多开了一个空间,那么就需要注意两个问题:

1. 初始化虚拟节点的值,要保证后面的填表是正确的;

2. 下标映射的关系。 

下面,我们分别来对这两个问题进行研究:

1. 初始化虚拟节点的值,要保证后面的填表是正确的

因为我们多开了一个空间,这个空间的值也就意味着后面的值正确与否,我们需要根据题目要求和状态表示来初始化这个虚拟空间的值:

状态表示:dp[i]表示解码方法数

那么这个虚拟空间的值应该被设置为1  ->  dp[0] = 1

那么为什么呢?

在计算dp[2]时,如果可以与前一个组合起来解码,那么需要加上dp[i-2],这样就正好是一种方法。

2. 下标映射的关系

由于我们多创建了一个空间,那么在填表的时候s中的下标就要统一减一。

5.1 优化之后代码 

class Solution {
public:
    int numDecodings(string s) {
        int n = s.size();
        // 多开一个空间
        vector<int> dp(n + 1);
        // 初始化
        dp[0] = 1;
        dp[1] = s[1 - 1] != '0';

        for(int i = 2; i<=n; i++)
        {
            // s的下标要对应-1
            if(s[i - 1] != '0') dp[i] += dp[i-1];
            int ret = (s[i-2] - '0')*10 + s[i - 1] - '0';
            if(ret >= 10 && ret <= 26) dp[i] += dp[i-2];
        }
        //多开一个空间所以返回第n个位置即可
        return dp[n];
    }
};

 

 

朋友们、伙计们,美好的时光总是短暂的,我们本期算法的分享就到此结束,欲知后事如何,请听下回分解~,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持! 

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

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

相关文章

【网工】华为设备命令学习(综合实验一)

实验要求和实验成果如图所示。 LSW2不需要其他配置&#xff0c;其下就一台设备&#xff0c;不需要区分。 LSW3配置如下&#xff1a; <Huawei>sy Enter system view, return user view with CtrlZ. [Huawei]un in en //关闭系统提示信息 Info: Information …

LeetCode、72. 编辑距离【中等,二维DP】

文章目录 前言LeetCode、72. 编辑距离【中等&#xff0c;二维DP】题目链接与分类二维DP 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领域。 涵盖技术内容…

VTK Python PyQt 监听键盘 控制 Actor 移动 变色

KeyPressInteractorStyle 在vtk 中有时我们需要监听 键盘或鼠标做一些事&#xff1b; 1. 创建 Actor&#xff1b; Sphere vtk.vtkSphereSource() Sphere.SetRadius(10)mapper vtk.vtkPolyDataMapper() mapper.SetInputConnection(Sphere.GetOutputPort()) actor vtk.vtkAc…

Vue核心基础6:Vue内置指令、自定义指令、生命周期

1 Vue中的内置指令 <script>const vm new Vue({el: #root,data: {n: 1,m: 100,name: Vue,str: <h3>你好</h3>}})</script> 1.1 v-text <div v-text"name"></div>1.2 v-html <div v-html"str"></div> …

Spring Boot 笔记 012 创建接口_添加文章分类

1.1.1 实体类添加校验 package com.geji.pojo;import jakarta.validation.constraints.NotEmpty; import lombok.Data;import java.time.LocalDateTime;Data public class Category {private Integer id;//主键IDNotEmptyprivate String categoryName;//分类名称NotEmptypriva…

中小学信息学奥赛CSP-J认证 CCF非专业级别软件能力认证-入门组初赛模拟题第一套(完善程序题)

CCF认证CSP-J入门组模拟测试题第一套 三、完善程序题 第一题 九宫格 请完善下面的程序,将1~9个数字分别填人3x3的九宫格中,第一行的三个数字组成一个三位数。要使第二行的三位数是第一行的2倍,第三行的三位数是第一行的3倍且每个格子里的数字都不能重复,现在要求输出所有的填…

python输出字符 2022年12月青少年电子学会等级考试 中小学生python编程等级考试二级真题答案解析

目录 python输出字符 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python输出字符 2022年12月 python编程等级考试级编程题 一、题目要求 …

《CSS 简易速速上手小册》第2章:CSS 布局与定位(2024 最新版)

文章目录 2.1 Flexbox&#xff1a;灵活的布局解决方案2.1.1 基础知识2.1.2 重点案例&#xff1a;创建一个响应式导航菜单2.1.3 拓展案例 1&#xff1a;卡片布局2.1.4 拓展案例 2&#xff1a;中心对齐的登录表单 2.2 Grid 布局&#xff1a;网格系统的魔力2.2.1 基础知识2.2.2 重…

渗透测试练习题解析 3(CTF web)

1、[网鼎杯 2020 朱雀组]phpweb 1 考点&#xff1a;反序列化漏洞利用 进入靶场&#xff0c;查看检查信息&#xff0c;发现存在两个参数 func 和 p 查看页面源代码 payload&#xff1a;funcfile_get_contents&pphp://filter/resourceindex.php 整理后&#xff0c;就是 PHP 代…

数据结构与算法:单链表

朋友们大家好&#xff0c;本节来到数据结构与算法的新内容&#xff1a;单链表 在上篇文章中&#xff0c;我们知道顺序表通常需要预分配一个固定大小的内存空间&#xff0c; 通常以二倍的大小进行增容&#xff0c;可能会造成空间的浪费&#xff0c;本篇文章我们介绍的链表可以解…

去除vue自带的边距

使用vue时发现总有去不掉的外边距&#xff0c;在index.vue里面怎样设置样式都不管用 查阅资料后发现要在vue项目自带的index.html文件内添加下面的样式代码才行 <style>*{margin: 0;padding: 0;}body,html{margin: 0;padding: 0;} </style>

二、DataX安装

DataX安装 一、简介二、系统要求三、部署 一、简介 官方地址&#xff1a;https://github.com/alibaba/DataX/blob/master/userGuid.md 二、系统要求 LinuxJDK(1.8以上&#xff0c;推荐1.8) Centos7.9的java1.8安装命令&#xff1a;yum install java-1.8.0-openjdk.x86_64 Py…

【新书推荐】7.6节 相对基址加变址寻址方式

本节内容&#xff1a;基址加变址寻址方式。 ■基址加变址寻址方式&#xff1a;指令操作数为内操作数&#xff0c;操作数地址使用[基址寄存器变址寄存器]表示。 7.6.1 基址加变址寻址方式 基址加变址寻址方式的操作数在存储器中&#xff0c;操作数的有效地址由基地址寄存器&am…

day 20(补2.5)

fread 函数&#xff1a; 今日练习 C语言面试题5道~ 1. static 有什么用途&#xff1f;&#xff08;请至少说明两种&#xff09; 1) 限制变量的作用域 2) 设置变量的存储域 2. 引用与指针有什么区别&#xff1f; 1) 引用必须被初始化&#xff0c;指针不必。 2) 引用初始…

幻兽帕鲁服务器原来的存档不想玩了,怎么清档?如何重来?

如果需要备份原存档的话&#xff0c;就先把存档导出来备份。或者手动去服务器文件里找到游戏存档文件夹&#xff0c;保存下载。 如无需备份原存档&#xff0c;则可以直接使用幻兽帕鲁应用模板&#xff0c;来重装服务器的操作系统。 方法很简单&#xff1a; 详细教程地…

mysql经典4张表问题

1.数据库表结构关联图 2.问题&#xff1a; 1、查询"01"课程比"02"课程成绩高的学生的信息及课程分数3.查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩4、查询名字中含有"风"字的学生信息5、查询课程名称为"数学"&…

网络协议与攻击模拟_17HTTPS 协议

HTTPShttpssl/tls 1、加密算法 2、PKI&#xff08;公钥基础设施&#xff09; 3、证书 4、部署HTTPS服务器 部署CA证书服务器 5、分析HTTPS流量 分析TLS的交互过程 一、HTTPS协议 在http的通道上增加了安全性&#xff0c;传输过程通过加密和身份认证来确保传输安全性 1、TLS …

【制作100个unity游戏之25】3D背包、库存、制作、快捷栏、存储系统、砍伐树木获取资源、随机战利品宝箱3(附带项目源码)

效果演示 文章目录 效果演示系列目录前言丢弃物品源码完结 系列目录 前言 欢迎来到【制作100个Unity游戏】系列&#xff01;本系列将引导您一步步学习如何使用Unity开发各种类型的游戏。在这第25篇中&#xff0c;我们将探索如何用unity制作一个3D背包、库存、制作、快捷栏、存…

netstat命令

netstat 是一个计算机网络命令行工具&#xff0c;用于显示网络连接、路由表和网络接口等网络相关信息。netstat 命令可以在各种操作系统上使用&#xff0c;包括 Windows、Linux 和 macOS 等。 在使用 netstat 命令时&#xff0c;可以提供不同的选项来显示不同类型的网络信息。…

助力智能化农田作物除草,基于轻量级YOLOv8n开发构建农田作物场景下玉米苗、杂草检测识别分析系统

在我们前面的系列博文中&#xff0c;关于田间作物场景下的作物、杂草检测已经有过相关的开发实践了&#xff0c;结合智能化的设备可以实现只能除草等操作&#xff0c;玉米作物场景下的杂草检测我们则少有涉及&#xff0c;这里本文的主要目的就是想要基于最新的YOLOv8下最轻量级…