剑指offer(C++)-JZ46:把数字翻译成字符串(算法-动态规划)

news2024/11/24 9:37:46

作者:翟天保Steven
版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处

题目描述:

有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。

现在给一串数字,返回有多少种可能的译码结果

数据范围:字符串长度满足 0<n≤90

进阶:空间复杂度 O(n),时间复杂度O(n)

示例1:

输入:

"12"

返回值:

2

说明:

2种可能的译码结果(”ab” 或”l”)

示例2:

输入:

"31717126241541717"

返回值:

192

说明:

192种可能的译码结果

解题思路:

本题是动态规划的经典题目。有两个解题思路,动态规划和动态规划进阶(空间复杂度低)。

本题难点在于0的情况,10和20则只代表1种结果,11-19或21-26能代表2种结果,0不代表任何情况且可能会导致解码失败,1-9代表1种结果。

思路一:动态规划

  1. 用长度比字符串长度多1的dp存储结果数。dp[0]初始化为1;i从1开始,dp[i]存放的是前i个数字可能的结果,所以dp[1]也为1,dp[2]开始就要分情况了。
  2. 若i-1为0,则i-2必须为1或2,编码才可能成功,10和20有字母,30及之后都没有对应字母了。那么有dp[i]等于dp[i-2],相当于dp[i]在dp[i-2]种可能的基础上多了一个双数字字母,多一个字母则结果数是一致的。
  3. 若i-2和i-1的位置能组合出11-19/21-26的数,则dp[i]相当于dp[i-1]和dp[i-2]之和。dp[i-1]表示截止到前i-1个数字可能的结果数,加上一个单数字对应的字母,是一类情况;dp[i-2]表示截止到前i-2个数字可能的结果数,加上一个双数字对应的字母,是一类情况。
  4. 若组合不出双数字字母,那就只能是单数字字母了,所以dp[i]等于dp[i-1]。相当于dp[i]在dp[i-1]种可能的基础上多了一个字母,多一个字母则结果数是一致的。
  5. 最后返回dp[size],size是字符串长度,就是size个字符可能的结果数。

思路二:动态规划进阶

       思路和思路一中基本一致。区别在于用pre和cur两个int数动态刷新,来实现动态规划,好处是空间复杂度降低,坏处是丢失了前面的结果数据只保留了最终结果。

       建议看懂思路一代码再看思路二代码。

测试代码:

思路一:动态规划

class Solution {
public:
    // 解码
    int solve(string nums) {
        // 排除开头为0的情况
        if(nums[0] == '0')
            return 0;
        // 动态规划
        // dp[0]初始化为1;i从1开始,dp[i]存放的是前i个数字可能的结果,所以dp[1]也为1,dp[2]开始就要分情况了
        vector<int> dp(nums.size()+1, 1);
        for(int i = 2; i <= nums.size(); ++i){
            // 注意字符串下标是从0开始
            // 若i-1为0,则当i-2为1或2时,编码才可能成功,10和20有字母,30及之后都没有对应字母了
            if(nums[i - 1] == '0'){
                // 若是10或20,则dp[i]等于dp[i-2],相当于dp[i]在dp[i-2]种可能的基础上多了一个字母,多一个字母则结果数是一致的
                if(nums[i - 2] == '1' || nums[i - 2] == '2')
                    dp[i] = dp[i - 2];
                else 
                    return 0;
            }
            // 若i-2和i-1的位置能组合出11-19/21-26的数,则dp[i]相当于dp[i-1]和dp[i-2]之和
            // dp[i-1]表示前i-1个数字可能的结果数,加上一个单数字对应的字母,是一类情况
            // dp[i-2]表示前i-2个数字可能的结果数,加上一个双数字对应的字母,是一类情况
            else if(nums[i - 2] == '1' || (nums[i - 2] == '2' && nums[i - 1] > '0' && nums[i - 1] < '7')){
                dp[i] = dp[i - 1] + dp[i - 2];
            }
            // 若组合不出双数字字母,那就只能是单数字字母了,所以dp[i]等于dp[i-1]
            // 相当于dp[i]在dp[i-1]种可能的基础上多了一个字母,多一个字母则结果数是一致的
            else{
                dp[i] = dp[i - 1];
            }
        }
        return dp[nums.size()];
    }
};

思路二:动态规划进阶


class Solution {
public:
    // 解码
    int solve(string nums) {
        // 排除开头为0的情况
        if(nums[0] == '0')
            return 0;
        // 动态规划
        // 用pre表示前i-1个字符的可能数,cur表示前i个字符的可能数
        vector<int> dp(nums.size()+1, 1);
        int pre = 1;
        int cur = 1;
        for(int i = 2; i <= nums.size(); ++i){
            // temp存储cur,因为cur马上要被覆盖了
            int temp = cur;
            // 注意字符串下标是从0开始
            // 若i-1为0,则当i-2为1或2时,编码才可能成功,10和20有字母,30及之后都没有对应字母了
            if(nums[i - 1] == '0'){
                // 若是10或20,则cur等于上一轮的pre,也就是比当前位置靠前2步的数值
                if(nums[i - 2] == '1' || nums[i - 2] == '2')
                    cur = pre;
                else 
                    return 0;
            }
            // 若i-2和i-1的位置能组合出11-19/21-26的数,则cur等于上一轮的cur和pre之和
            // 上一轮的cur表示前i-1个数字可能的结果数,加上一个单数字对应的字母,是一类情况
            // 上一轮的pre表示前i-2个数字可能的结果数,加上一个双数字对应的字母,是一类情况
            else if(nums[i - 2] == '1' || (nums[i - 2] == '2' && nums[i - 1] > '0' && nums[i - 1] < '7')){
                cur = cur + pre;
            }
            // 若组合不出双数字字母,那就只能是单数字字母了,所以cur相比上一轮的cur无数值变化,这段代码也可以删除,为了便于分情况理解我加上了
            else{
                cur = cur;
            }
            // 这一轮的pre等于上一轮的cur
            pre = temp;
        }
        return cur;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何在Angular应用程序中插入自定义 CSS?这里有答案!

Kendo UI for Angular是专用于Angular开发的专业级Angular组件&#xff0c;telerik致力于提供纯粹的高性能Angular UI组件&#xff0c;无需任何jQuery依赖关系。 Kendo UI R1 2023正式版下载(Q技术交流&#xff1a;726377843&#xff09; 为什么需要在 Angular 应用程序中插入…

兼容性测试点和注意项,建议收藏

一&#xff1a;兼容性测试的概念&#xff1a;就是验证开发出来的程序在特定的运行环境中与特定的软件、硬件或数据相组合是否能正常运行、有无异常的测试过程。 二&#xff1a;兼容性测试的分类&#xff1a; &#xff08;1&#xff09;浏览器兼容性测试 指的是在浏览器上检查…

航空公司预订票数学建模论文

航空公司预订票数学建模论文篇1 试谈机票订票模型与求解 一、概述 1. 问题背景描述 在激烈的市场竞争中&#xff0c;航空公司为争取更多的客源而开展的一个优质服务项目是预订票业务,本模型针对预订票业务&#xff0c;建立二元规划订票方案&#xff0c;既考虑航空公司的利润最大…

form-create和form-create-designer创建自定义组件

在项目中&#xff0c;我需要使用表单设计器form-create-designer设计带有选择用户的弹窗组件&#xff0c;而设计器内置的组件不能满足需求&#xff0c;因此要创建自定义组件。form-create 支持在表单内部生成任何 vue 组件。 1.开发选择用户的组件 SelectUser.vue <!--用户…

论文《Diagnostic accuracy of CT imaging parameters in pelvic lipomatosis》案例分析

一、引言 在该篇文章的引言部分&#xff0c;作者明确阐述了本篇论文的研究目的、问题和方法&#xff0c;并指出了研究的贡献和创新点。以下是具体内容&#xff1a; 研究目的&#xff1a;本研究的目的是评估盆腔脂肪肥大的CT成像特征&#xff0c;并探讨其在诊断和管理中的应用…

Java程序设计入门教程--包

情形 在Java中&#xff0c;包(package)是一种松散的类的集合&#xff0c;它可以将各种类文件组织在一起&#xff0c;就像磁盘的目录&#xff08;文件夹&#xff09;一样。包的管理机制提供了类的多层次命名空间避免了命名冲突问题&#xff0c;解决了类文件的组织问题&#xff0…

Midjourney AI绘画中文教程(完整版)

我有一种预感&#xff0c;这篇内容一定会破万~~~ Midjourney AI绘画中文教程&#xff0c;Midjourney是一款2022年3月面世的AI绘画工具&#xff0c;创始人是David Holz。 只要输入想到的文字&#xff0c;就能通过人工智能产出相对应的图片&#xff0c;耗时只有大约一分钟&…

Linux Shell 实现部署单机Oracle 21C

oracle前言 Oracle开发的关系数据库产品因性能卓越而闻名&#xff0c;Oracle数据库产品为财富排行榜上的前1000家公司所采用&#xff0c;许多大型网站也选用了Oracle系统&#xff0c;是世界最好的数据库产品。此外&#xff0c;Oracle公司还开发其他应用程序和软件。同时&#…

《Spring Guides系列学习》guide1 - guide5

要想全面快速学习Spring的内容&#xff0c;最好的方法肯定是先去Spring官网去查阅文档&#xff0c;在Spring官网中找到了适合新手了解的官网Guides&#xff0c;一共68篇&#xff0c;打算全部过一遍&#xff0c;能尽量全面的了解Spring框架的每个特性和功能。 开始吧&#xff0…

UDP就一定比TCP快吗?

前言 话说&#xff0c;UDP比TCP快吗&#xff1f; 相信就算不是八股文老手&#xff0c;也会下意识的脱口而出&#xff1a;”是“。 但这也让人好奇&#xff0c;用UDP就一定比用TCP快吗&#xff1f;什么情况下用UDP会比用TCP慢&#xff1f; 我们今天就来聊下这个话题。 使用…

关于使用--- pyinstaller---无法打包py文件为exe的问题集合

目录 安装 pyinstaller 问题1&#xff1a; 解决办法&#xff1a; CMD中输入 问题2&#xff1a; 解决办法&#xff1a; CMD中输入 问题3&#xff1a; 将py文件打包成exe中&#xff0c;需要按照如下在CMD中输入 PyInstaller介绍 PyInstaller是一个Python库&#xff0c;可以…

智慧档案馆八防是怎么建设的?都需要注意哪些内容

智慧档案馆八防环境监控系统一体化解决系统方案 智慧档案库房一体化平台通过智慧档案管理&#xff0c;实现智慧档案感知协同处置功能&#xff1b;实现对档案实体的智能化识别、定位、跟踪监控&#xff1b;实现对档案至智能密集架、空气恒湿净化一体设备、安防设备&#xff0c…

基于java用队列实现栈

基于java用队列实现栈 问题描述 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void push(int x) 将元素 x 压入栈顶。 int …

C++第六章:函数

函数 一、函数基础1.0 简介形参和实参形参列表函数的返回类型 1.1 局部对象自动对象局部静态对象 1.2 函数声明在头文件中进行函数声明 1.3 分离式编译编译和链接多个源文件 二、参数传递2.1 传值参数指针形参 2.2 传引用参数使用形参返回额外信息 2.3 const形参和实参指针或引…

「实在RPA·人社数字员工」促进人力社保数字办公战略转型

一、人力社保部门数字化转型的重要性 伴随着国家放宽人力资源市场准入条例&#xff0c;多次出台相关扶持政策&#xff0c;市场竞争加剧&#xff0c;后疫情时代格局的大变局&#xff0c;如何提高服务质量和效率&#xff0c;如何降本增效&#xff0c;成为人力资源和社会保障行业…

【算法】不使用LinkedHashMap实现一个LRU缓存

文章目录 什么是LRU&#xff1f;设计思路代码实现 LRU是我在面试过程中遇到的比较多的算法题了&#xff0c;并且我自己的项目中也手写了LRU算法&#xff0c;所以觉得还是有必要掌握一下这个重要的算法的。 什么是LRU&#xff1f; LRU是一种缓存淘汰策略。 我们知道&#xff0…

经典文献阅读之--PIBT(基于可见树的实时规划方案)

0. 简介 作为路径规划而言&#xff0c;不单单有单个机器人自主路径规划&#xff0c;近年来随着机器人行业的兴起&#xff0c;多机器人自主路径规划也越来越受到关注&#xff0c;对于多智能体寻路(MAPF)。一般的操作会给定一个地图、机器人集群、以及它们的初始位置和目的地&am…

IP地址分配与释放

IP 分配我们平时应该接触比较少。还记得在大学的时候&#xff0c;刚入学第一件事就是赶紧交网费。交网费时会有一个步骤&#xff0c;网管会让你提供 MAC 地址&#xff0c;然后把 IP 地址和 MAC 地址绑定&#xff0c;这也就是博主在隔壁宿舍无法通过网线上网的原因。 其实&#…

如何在华为OD机试中获得满分?Java实现【寻找相似单词】一文详解!

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: Java华为OD机试真题&#xff08;2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述…

[已解决] 决定系数R2为何为负 from sklearn.metrics import r2_score

最近在炼丹发现一件很有趣的现象&#xff0c;决定系数R2竟然为负&#xff0c;小学生都知道任何一个常数的平方绝不可能为负&#xff0c;潜意识里告诉我这里面必有蹊跷&#xff0c;因此查阅许多资料得知&#xff0c;决定系数R2不是r相关系数的平方这么简单&#xff0c;实际上当非…