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,一经查实,立即删除!

相关文章

Nginx入门到精通

介绍 Nginx是一个高性能的Web服务器&#xff0c;它可以处理大量的并发请求&#xff0c;同时还可以作为负载均衡器和反向代理服务器。在本篇博文中&#xff0c;我们将介绍如何从入门到精通Nginx的使用。 Nginx的安装和配置 在开始使用Nginx之前&#xff0c;您需要先安装和配置…

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

当国内的用户想要使用国外的产品时&#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;。该项目展示了数字孪生的分拣机与一些额外的功能。该应用程序使用多线程…

使用 for 来遍历枚举的元素

#include <stdio.h> enum DAY { MON1, TUE, WED, THU, FRI, SAT, SUN } day; int main() { // 遍历枚举元素 for (day MON; day < SUN; day) { printf("枚举元素&#xff1a;%d \n", day); } }

DolphinDB教程:实时计算高频因子

DolphinDB教程&#xff1a;实时计算高频因子 DolphinDB是一款高性能分布式时序数据库。与传统的关系数据库和常见的时序数据库不同&#xff0c;DolphinDB不仅提供了高速存取时序数据的基本功能&#xff0c;而且内置了向量化的多范式编程语言与强大的计算引擎。DolphinDB的计算引…

S32 Design Studio PE工具配置ADC

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

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

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

python 中的enumerate函数

在Python中&#xff0c;enumerate()函数用于将一个可遍历的数据对象&#xff08;如列表、元组或字符串&#xff09;组合为一个索引序列&#xff0c;同时列出数据下标和数据&#xff0c;一般用在for循环中。 enumerate()函数的语法是&#xff1a; enumerate(iterable, start0)…

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

、此方法可以直接下发打印机&#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 []…

【JS】Object的静态方法

前言 像map、filter、some等方法都是Object实例的方法&#xff0c;即原型链方法。 Object的静态方法不依赖于任何对象实例&#xff0c;而是直接调用Object类本身。 常用静态方法如下&#xff1a; 一、Object.assign(target,…source) 将一个或多个源对象的属性复制到目标对…

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

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

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

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

CF476D Dreamoon and Sets 题解 贪心

Dreamoon and Sets 传送门 Dreamoon likes to play with sets, integers and gcd ⁡ \gcd gcd . gcd ⁡ ( a , b ) \gcd(a,b) gcd(a,b) is defined as the largest positive integer that divides both a a a and b b b . Let S S S be a set of exactly four distinct…

网络编程套接字(2)——Socket套接字

目录 一、概念 二、分类 1、流套接字&#xff08;使用传输层TCP协议&#xff09; TCP的特点 2、数据报套接字&#xff08;使用传输层UDP协议&#xff09; UDP的特点 3、原始套接字 一、概念 Socket套接字&#xff0c;是由系统提供用于网络通信的技术&#xff0c;是基于T…

ORACLE RAC ADG容灾实施

--1、主库检查 检查修改主库的force logging 模式 sqlplus / as sysdba SQL>select FORCE_LOGGING from v$database; alter database force logging; --主库remote_login_passwordfile 为EXCLUSIVE show parameter remote_login_passwordfile ---2、主库参数 alter …

处理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;讲一下基础的数据类型 就记得元组和字典 分别具体说一下元组和字典 流程控制语句有哪些&…