LeetCode-91题:解码方法(原创)

【题目描述】

一条包含字母 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 位 的整数。

【题目链接】. - 力扣(LeetCode)

【解题代码】

package dp;public class NumDecodings {public static void main(String[] args) {long start = System.currentTimeMillis();// String s = "106";//String s = "10";//String s = "06";//String s = "11106";String s = "111111111111111111111111111111111111111111111";int result = new NumDecodings().numDecodings(s);System.out.println("result = " + result);System.out.println("函数执行时间:" + (System.currentTimeMillis() - start) + "MS");}public int numDecodings(String s) {// 按照惯例定义一个dp数组int[] dp = new int[s.length()];char ch1 = s.charAt(0);// 设置dp[0]值,如果第一个字符为合法解码,那么设置为1,否则为0dp[0] = ch1 > 48 ? 1 : 0;// 依次遍历后续字符for (int i = 1; i < dp.length; i++) {char ch2 = s.charAt(i);// 计算当前字符和上一个字符组合解码值:等于((ch1-48)*10+ch2-48),即(ch1*10 +ch2-528)char num = (char) (ch1 * 10 + ch2 - 528);// 如果当前字符是合法解码,那么当前字符可以作为一个单独解码加入上一个字符的解码分组里,在这种情况下,解码数就等于上一字符解码数if (ch2 > 48) {dp[i] = dp[i - 1];}// 如果上一个字符是合法解码,并且当前字符和上一个字符之和也是合法解码if (ch1 > 48 && num < 27) {// 如果i值大于1,那么当前字符和上一个字符组合解码加入上上个字符的解码分组里,在这种情况下,解码数要加上于上上个字符解码数if (i > 1) {dp[i] += dp[i - 2];} else { // 如果i值等于2,那么就多一个当前字符和上一个字符组合解码dp[i] += 1;}}// 更新ch1为ch2值ch1 = ch2;}return dp[s.length() - 1];}// 递归实现方式,速度慢public int numDecodings1(String s) {return numDecodings1(s, 0);}private int numDecodings1(String s, int n) {if (n == s.length()) {return 1;}int result = 0;char ch1 = s.charAt(n);// 当前字符是合法解码,那么将当前字符作为一个解码和之后所有字符放在一个分组if (ch1 > 48) {// 当前解码数等于之后所有字符解码result = numDecodings1(s, n + 1);if (n < s.length() - 1) {// 计算当前字符和下一个字符组合解码值:等于((ch1-48)*10+ch2-48),即(ch1*10 +ch2-528)char ch2 = (char) (ch1 * 10 + s.charAt(n + 1) - 528);// 如果当前字符和下个字符之和也是合法解码,那么解码数再加上去掉这两个字符之后所有字符解码if (ch2 < 27) {result += numDecodings1(s, n + 2);}}}return result;}
}

【解题思路】

分析题目可得知,一个字符要么单独解码,要么和下一个字符进行解码,一开始最简单的思路就是采用递归的方式:从第一个字符开始,首先如果当前字符是合法解码,那么将当前字符作为一个解码和之后所有字符放在一个分组,即当前解码数等于之后所有字符解码数。再次如果当前字符和下个字符之和也是合法解码,那么解码数再加上去掉这两个字符之后所有字符解码。递归这种方式容易思考,但估计速度慢,先写出来试试看,代码如下:

// 递归实现方式,速度慢
public int numDecodings1(String s) {return numDecodings1(s, 0);
}private int numDecodings1(String s, int n) {if (n == s.length()) {return 1;}int result = 0;char ch1 = s.charAt(n);// 当前字符是合法解码,那么将当前字符作为一个解码和之后所有字符放在一个分组if (ch1 > 48) {// 当前解码数等于之后所有字符解码result = numDecodings1(s, n + 1);if (n < s.length() - 1) {// 计算当前字符和下一个字符组合解码值:等于((ch1-48)*10+ch2-48),即(ch1*10 +ch2-528)char ch2 = (char) (ch1 * 10 + s.charAt(n + 1) - 528);// 如果当前字符和下个字符之和也是合法解码,那么解码数再加上去掉这两个字符之后所有字符解码if (ch2 < 27) {result += numDecodings1(s, n + 2);}}}return result;}

不出所料,提交之后。LeetCode系统报错:超出时间限制:

本地试了一下,运行时长高达13414毫秒,唉,递归方式太不靠谱了,还是回到我们的“动态规划”大法的正途之中去;

按照动态规划的“过把原问题分解为相对简单的子问题的方式求解复杂问题的方法”的模式化套路,反复深度思考,终于得到以下几个要点:

  1. 如果当前字符是合法解码,那么当前字符可以作为一个单独解码加入上一个字符的解码分组里,在这种情况下,解码数就等于上一字符解码数;
    dp[i] = dp[i - 1];
  2. 如果上一个字符是合法解码,并且当前字符和上一个字符之和也是合法解码,那么当前字符和上一个字符组合解码加入上上个字符的解码分组里,在这种情况下,解码数要加上于上上个字符解码数
    dp[i] += dp[i - 2];

思路一打开,解题就简单了,且看下面解题步骤

【解题步骤】

  1.  按照惯例定义一个dp数组
    int[] dp = new int[s.length()];
  2. 设置dp[0]值,如果第一个字符为合法解码,那么设置为1,否则为0
    char ch1 = s.charAt(0);
    dp[0] = ch1 > 48 ? 1 : 0;
  3. 依次遍历后续所有字符,获取当前字符,以及当前字符和上个字符的组合解码值
     // 依次遍历后续字符for (int i = 1; i < dp.length; i++) {char ch2 = s.charAt(i);// 计算当前字符和上一个字符组合解码值:等于((ch1-48)*10+ch2-48),即(ch1*10 +ch2-528)char num = (char) (ch1 * 10 + ch2 - 528);
  4. 如果当前字符是合法解码,那么当前字符可以作为一个单独解码加入上一个字符的解码分组里,在这种情况下,解码数就等于上一字符解码数
    if (ch2 > 48) {dp[i] = dp[i - 1];
    }
  5. 如果上一个字符是合法解码,并且当前字符和上一个字符之和也是合法解码:
    1)如果i值大于1,那么当前字符和上一个字符组合解码加入上上个字符的解码分组里,在这种情况下,解码数要加上于上上个字符解码数
    2)如果i值等于2,那么就多一个当前字符和上一个字符组合解码
    if (ch1 > 48 && num < 27) {if (i > 1) {dp[i] += dp[i - 2];} else { // 如果i值等于2,那么就多一个当前字符和上一个字符组合解码dp[i] += 1;}
    }
  6. 循环尾句,更新上个字符为当前字符
    ch1 = ch2;
  7. 循环结束,dp数组最后一个值就是所求答案,最后返回即可
    return dp[s.length() - 1];
  8. 最后提交代码,顺利0毫秒通过,本地把刚才超时的例子 "111111111111111111111111111111111111111111111"跑了一下,也是0毫秒,大功告成,顺利收工。    

【思考总结】

  1. 对于此类问题,“动态规划”是王道,递归方式容易思考,但是存在大量的重复计算,性能远远和动态规划无法相比;
  2. 动态规划是优化版的递归,通过储存子问题的解避免重复计算,提高效率,适合解决有重叠子问题和最优子结构的问题。而递归直接通过函数自调用解决问题,简单直观但可能效率低下因为重复计算。动态规划自底向上,递归自顶向下。。
  3. 对于王道的动态规划,再复习下其思想精髓
  4. LeetCode解题之前,一定不要看题解,看了就“破功”了!

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

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

相关文章

如何获取国外信用卡?需要国外银行卡支付怎么解决?如何订阅国外产品?

当国内的用户想要使用国外的产品时&#xff0c;很多产品是需要订阅付费的。其中有些产品还没有引入国内&#xff0c;只能用国外的信用卡支付&#xff0c;对于在国内的朋友&#xff0c;如何获取一张国外的信用卡呢&#xff1f; 这里推荐一个平台&#xff1a;wildCard waildCard…

2核4g服务器能支持多少人访问?并发数性能测评

2核4g服务器能支持多少人访问&#xff1f;支持80人同时访问&#xff0c;阿腾云使用阿里云2核4G5M带宽服务器&#xff0c;可以支撑80个左右并发用户。阿腾云以Web网站应用为例&#xff0c;如果视频图片媒体文件存储到对象存储OSS上&#xff0c;网站接入CDN&#xff0c;还可以支持…

String 的使用注意事项

String类型变量不可变 string类型的变量不可变&#xff0c;下面的拼接是怎么回事呢? // 拼接字符串 String str1 "hello"; String str2 "world"; String str3 str1 str2; System.out.println(str3);拼接都会新建 一个常量字符串一个拼接之后的字符串 …

【Unity】分拣机的数字双胞胎集成到Unity3D开发平台中

Unity HMI 一、前言 该项目的重点是通过OPC UA进行客户端-服务器通信的简单演示&#xff0c;该演示在Unity3D中实现&#xff08;服务器- B&R Automation PLC&#xff0c;客户端- Unity3D&#xff09;。该项目展示了数字孪生的分拣机与一些额外的功能。该应用程序使用多线程…

S32 Design Studio PE工具配置ADC

工具配置 我这个K1芯片有两个ADC驱动&#xff0c;也就有两个components&#xff0c;点开之后每个components都有四个选项卡converter转换器、channel通道、compare比较器、average求平均。 配置引脚 配置之前&#xff0c;得先配置好引脚&#xff0c;哪个引脚用来采集ADC。 每…

亚洲股市下一步的关键:中国看财报、日本看汇率、韩国看治理、印度看基建

汇丰认为财报将是驱动中国股市走势的关键因素。目前市场预计2024年中国企业每股收益将增长16%。 日本央行转向、A股业绩复苏、印度基建、韩国市场改革......最近这段时间&#xff0c;亚洲各大市场涌现出了不同的交易主题。 汇丰银行指出&#xff0c;中国受到本土企业盈利能力…

域控操作八:下发打印机策略

、此方法可以直接下发打印机&#xff0c;加域OU后自动连接 1&#xff0c;在域控服务器上安装打印机确保域控可以让打印机使用 并且要开共享入目录 这个共享路径正常情况下应该是在运行里面输入是直接能连接打印机的

算法——链表王

链表刷题详解 203.移除链表元素 力扣题目链接(opens new window) 题意&#xff1a;删除链表中等于给定值 val 的所有节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 示例 2&#xff1a; 输入&#xff1a;head []…

数据库(mysql)-新手笔记(主外键,视图)

主外键 主键(唯一性,非空性) 主键是数据库表中的一个或多个字段&#xff0c;其值唯一标识表中的每一行/记录。 唯一性: 主键字段中的每个值都必须是唯一的&#xff0c;不能有两个或更多的记录具有相同的主键值 非空性&#xff1a;主键字段不能包含NULL值。 外键(引用完整 …

AutoPSA里给定了弹簧刚度,为什么计算没有引用?

山东一用户问&#xff1a;已经给定了弹簧刚度&#xff0c;为什么计算没引用&#xff1f; 在AutoPSA里包含两种算法仿CAESARII &#xff0c;仿GLIF算法。 在仿CAESARII算法里直接给定弹簧刚度与安载荷载&#xff0c;两个都给了相应值&#xff0c;也就是给定了弹簧号&#xff1b…

处理error: remote origin already exists.及其Gitee文件上传保姆级教程

解决error: remote origin already exists.&#xff1a; 删除远程 Git 仓库 git remote rm origin 再添加远程 Git 仓库 git remote add origin &#xff08;HTTPS&#xff09; 比如这样&#xff1a; 然后再push过去就ok了 好多人可能还是不熟悉怎么将文件上传 Gitee:我…

Python实习生(自动化测试脚本开发) - 面经 - TCL新技术有限公司

JD&#xff1a; 招聘流程&#xff1a; 2024.1.3 Boss直聘 沟通 2024.1.4 约面 2024.1.6 上午面试 面试流程&#xff1a; 上来第一步&#xff0c;直接问Python基础语法&#xff0c;讲一下基础的数据类型 就记得元组和字典 分别具体说一下元组和字典 流程控制语句有哪些&…

应急布控球远程视频监控方案:视频监控平台EasyCVR+4G/5G应急布控球

随着科技的不断发展&#xff0c;应急布控球远程视频监控方案在公共安全、交通管理、城市管理等领域的应用越来越广泛。这种方案通过在现场部署应急布控球&#xff0c;实现对特定区域的实时监控&#xff0c;有助于及时发现问题、快速响应&#xff0c;提高管理效率。 智慧安防视…

SPFA找负环

2024-01-31&#xff08;最短路径&#xff09;-CSDN博客 求负环的常用方法&#xff0c;基于spfa&#xff1a; 1.统计每个点入队的次数&#xff0c;如果有个点入队n次&#xff0c;则说明存在负环 2.统计当前每个点的最短路中包含的边数&#xff0c;如果某个点的最短路的所包含的边…

QT:用opencv的KNN识别图片中的LED数字(一)

前言 一款功能测试的软件demo,使用了QT作为界面,主要使用了opencv的KNN识别,使用gstreamer作为管道,用来打开图片。后期会写一篇打开摄像头实时识别的文章。 (正在写,未完成,稍候) 效果一预览: 效果二预览: 效果三预览: 正在写。。。 设计思路 1. 软件UI设…

【uni-app】condition 启动模式配置,生产环境无效,仅开发期间生效

在小程序开发过程中&#xff0c;每次代码修改后&#xff0c;都会启动到首页&#xff0c;有时非常不方便&#xff0c;为了更高效的开发&#xff0c;有时需要模拟直接跳转到指定的页面&#xff0c; 操作方法如下&#xff1a; 在pages.joson里面配置下列代码&#xff1a; "…

Mybatis-Spring | Mybatis与Spring的“整合“

目录 : 一、配置环境1. 整合环境需导入的JAR :Spring框架所需JARMybatis框架所需JARMyBatis与Spring整合的中间JAR数据库驱动JAR包数据源所需JAR包 &#xff08;下面的例子中 : 用的不是这个数据源&#xff09; 2. 编写“配置文件” 和 “.properties文件” ( 只是概述&#xf…

Claude3真的超越GPT4了吗?

一文探究Claude3真实能力 Claude3就在昨天悄无声息的上线了&#xff0c;OpenAI的好兄弟Anthropic公司仅仅在推特上发了一条消息来宣布这件事情。 Anthropic这次一下就发了三个模型&#xff1a;Opus、Sonnet、Haiku。说实话这名字感觉取得不咋地&#xff0c;主要是看不懂&#x…

图机器学习(3)-面向节点的人工特征工程

0 问题引入 地铁导航图 计算机是看不懂这些图&#xff0c;计算机只能看懂向量、矩阵。 传统图机器学习只讨论连接特征。 构造一个新的特征 x 1 x 2 x_1x_2 x1​x2​&#xff0c;有利于分开这种数据。 人需要去翻译这些计算机不懂的特征&#xff0c;变成计算机可以懂…

javaSE-----继承和多态

目录 一.初识继承&#xff1a; 1.1什么是继承&#xff0c;为什么需要继承&#xff1a; 1.2继承的概念与语法&#xff1a; 二.成员的访问&#xff1a; 2.1super关键字 2.2this和super的区别&#xff1a; 三.再谈初始化: 小结&#xff1a; 四.初识多态&#xff1a; 4.1多…