[LeetCode] 91. Decode Ways 解码方法
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given a non-empty string containing only digits, determine the total number of ways to decode it.
Example 1:
Input: "12"
Output: 2
Explanation: It could be decoded as "AB" (1 2) or "L" (12).
Example 2:
Input: "226"
Output: 3
Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).
这道题要求解码方法,跟之前那道 Climbing Stairs 非常的相似,但是还有一些其他的限制条件,比如说一位数时不能为0,两位数不能大于 26,其十位上的数也不能为0,除去这些限制条件,跟爬梯子基本没啥区别,也勉强算特殊的斐波那契数列,当然需要用动态规划 Dynamci Programming 来解。建立一维 dp 数组,其中 dp[i] 表示s中前i个字符组成的子串的解码方法的个数,长度比输入数组长多多1,并将 dp[0] 初始化为1。现在来找状态转移方程,dp[i] 的值跟之前的状态有着千丝万缕的联系,就拿题目中的例子2来分析吧,当 i=1 时,对应s中的字符是 s[0]='2',只有一种拆分方法,就是2,注意 s[0] 一定不能为0,这样的话无法拆分。当 i=2 时,对应s中的字符是 s[1]='2',由于 s[1] 不为0,那么其可以被单独拆分出来,就可以在之前 dp[i-1] 的每种情况下都加上一个单独的2,这样 dp[i] 至少可以有跟 dp[i-1] 一样多的拆分情况,接下来还要看其能否跟前一个数字拼起来,若拼起来的两位数小于等于26,并且大于等于 10(因为两位数的高位不能是0),那么就可以在之前 dp[i-2] 的每种情况下都加上这个二位数,所以最终 dp[i] = dp[i-1] + dp[i-2],是不是发现跟斐波那契数列的性质吻合了。所以0是个很特殊的存在,若当前位置是0,则一定无法单独拆分出来,即不能加上 dp[i-1],就只能看否跟前一个数字组成大于等于 10 且小于等于 26 的数,能的话可以加上 dp[i-2],否则就只能保持为0了。具体的操作步骤是,在遍历的过程中,对每个数字首先判断其是否为0,若是则将 dp[i] 赋为0,若不是,赋上 dp[i-1] 的值,然后看数组前一位是否存在,如果存在且满足前一位是1,或者和当前位一起组成的两位数不大于 26,则当前 dp[i] 值加上 dp[i - 2]。最终返回 dp 数组的最后一个值即可,代码如下:
C++ 解法一:
class Solution {
public:
int numDecodings(string s) {
if (s.empty() || s[] == '') return ;
vector<int> dp(s.size() + , );
dp[] = ;
for (int i = ; i < dp.size(); ++i) {
dp[i] = (s[i - ] == '') ? : dp[i - ];
if (i > && (s[i - ] == '' || (s[i - ] == '' && s[i - ] <= ''))) {
dp[i] += dp[i - ];
}
}
return dp.back();
}
};
Java 解法一:
class Solution {
public int numDecodings(String s) {
if (s.isEmpty() || s.charAt() == '') return ;
int[] dp = new int[s.length() + ];
dp[] = ;
for (int i = ; i < dp.length; ++i) {
dp[i] = (s.charAt(i - ) == '') ? : dp[i - ];
if (i > && (s.charAt(i - ) == '' || (s.charAt(i - ) == '' && s.charAt(i - ) <= ''))) {
dp[i] += dp[i - ];
}
}
return dp[s.length()];
}
}
下面这种方法跟上面的方法的思路一样,只是写法略有不同:
C++ 解法二:
class Solution {
public:
int numDecodings(string s) {
if (s.empty() || s[] == '') return ;
vector<int> dp(s.size() + , );
dp[] = ;
for (int i = ; i < dp.size(); ++i) {
if (s[i - ] != '') dp[i] += dp[i - ];
if (i >= && s.substr(i - , ) <= "" && s.substr(i - , ) >= "") {
dp[i] += dp[i - ];
}
}
return dp.back();
}
};
Java 解法二:
class Solution {
public int numDecodings(String s) {
if (s.isEmpty() || s.charAt(0) == '0') return 0;
int[] dp = new int[s.length() + 1];
dp[0] = 1;
for (int i = 1; i < dp.length; ++i) {
if (s.charAt(i - 1) != '0') dp[i] += dp[i - 1];
if (i >= 2 && (s.substring(i - 2, i).compareTo("10") >= 0 && s.substring(i - 2, i).compareTo("26") <= 0)) {
dp[i] += dp[i - 2];
}
}
return dp[s.length()];
}
}
我们再来看一种空间复杂度为 O(1) 的解法,用两个变量 a, b 来分别表示 s[i-1] 和 s[i-2] 的解码方法,然后从 i=1 开始遍历,也就是字符串的第二个字符,判断如果当前字符为 '0',说明当前字符不能单独拆分出来,只能和前一个字符一起,先将 a 赋为0,然后看前面的字符,如果前面的字符是1或者2时,就可以更新 a = a + b,然后 b = a - b,其实 b 赋值为之前的 a,如果不满足这些条件的话,那么 b = a,参见代码如下:
C++ 解法三:
class Solution {
public:
int numDecodings(string s) {
if (s.empty() || s[] == '') return ;
int a = , b = , n = s.size();
for (int i = ; i < n; ++i) {
if (s[i] == '') a = ;
if (s[i - ] == '' || (s[i - ] == '' && s[i] <= '')) {
a = a + b;
b = a - b;
} else {
b = a;
}
}
return a;
}
};
Java 解法三:
class Solution {
public int numDecodings(String s) {
if (s.isEmpty() || s.charAt(0) == '0') return 0;
int a = 1, b = 1, n = s.length();
for (int i = 1; i < n; ++i) {
if (s.charAt(i) == '0') a = 0;
if (s.charAt(i - 1) == '1' || (s.charAt(i - 1) == '2' && s.charAt(i) <= '6')) {
a = a + b;
b = a - b;
} else {
b = a;
}
}
return a;
}
}
Github 同步地址:
https://github.com/grandyang/leetcode/issues/91
类似题目:
参考资料:
https://leetcode.com/problems/decode-ways/
https://leetcode.com/problems/decode-ways/discuss/30384/a-concise-dp-solution
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] 91. Decode Ways 解码方法的更多相关文章
- Leetcode 91. Decode Ways 解码方法(动态规划,字符串处理)
Leetcode 91. Decode Ways 解码方法(动态规划,字符串处理) 题目描述 一条报文包含字母A-Z,使用下面的字母-数字映射进行解码 'A' -> 1 'B' -> 2 ...
- [leetcode]91. Decode Ways解码方法
A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...
- leetcode@ [91] Decode Ways (Dynamic Programming)
https://leetcode.com/problems/decode-ways/ A message containing letters from A-Z is being encoded to ...
- leetcode 91 Decode Ways I
令dp[i]为从0到i的总方法数,那么很容易得出dp[i]=dp[i-1]+dp[i-2], 即当我们以i为结尾的时候,可以将i单独作为一个字母decode (dp[i-1]),同时也可以将i和i-1 ...
- [LeetCode] Decode Ways 解码方法
A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...
- [LeetCode] Decode Ways 解码方法个数、动态规划
A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...
- [LintCode] Decode Ways 解码方法
A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...
- 091 Decode Ways 解码方法
包含 A-Z 的字母的消息通过以下规则编码:'A' -> 1'B' -> 2...'Z' -> 26给定一个包含数字的编码消息,请确定解码方法的总数.例如,给定消息为 "1 ...
- Leetcode91.Decode Ways解码方法
一条包含字母 A-Z 的消息通过以下方式进行了编码: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 给定一个只包含数字的非空字符串,请计算解码方法的总数. 示例 1 ...
随机推荐
- CentOS下安装FreeTDS
导读 官方网站:http://www.freetds.org 下载地址:http://ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-stable ...
- Visual Studio 定制模板类---详细步骤
1.先定义一个类文件,将要定义的信息写入类文件 比如我每次写一个命令都是这个套路,要继承接口,要写上相应的特性,每次都 是重复的工作: 2.提取类模板 项目=>导出模板 这里你可以导出项目模板和 ...
- mysql mysqldump 命令导出指定表的数据
.导出指定表的数据 mysqldump -t database -u username -ppassword --tables table_name1 table_name2 table_name3 ...
- 深入理解Java对象
深入理解Java对象(理清关系) 1.对象的创建过程: 所有创建过程如下所示: new 类名 根据new的参数在常量池中定位一个类的符号引用. 如果没有找到这个符号引用,说明类还没有被加载,则进行类的 ...
- php动态拼接变量名,可变变量,动态变量,使用花括号,使用两个$符
php动态拼接变量名,可变变量,动态变量,使用花括号,使用两个$符方式一:使用花括号,前缀部分不需要用单引号$nums10 = 100;$xxx*${bcount.$nums10}['m54']/$n ...
- Jenkins+gradle+git部署
感谢博友分享,这边记录下https://blog.csdn.net/jiankeufo/article/details/78228334 我的密码7789cc2b62114e9da9fb78b0aa3 ...
- 基于Docker实现MySQL主从复制
前言 MySQL的主从复制是实现应用的高性能,高可用的基础.对于数据库读操作较密集的应用,通过使数据库请求负载均衡分配到不同MySQL服务器,可有效减轻数据库压力.当遇到MySQL单点故障中,也能在短 ...
- Git的认识与使用
Git教程 https://www.liaoxuefeng.com/wiki/896043488029600/897271968352576 Git与SVN区别 Git 不仅仅是个版本控制系统,它也是 ...
- day06 作业
猜年龄游戏 ''' 1. 给定年龄,用户可以猜三次年龄 2. 年龄猜对,让用户选择两次奖励 3. 用户选择两次奖励后可以退出 ''' import random age = random.randin ...
- odoo10学习笔记二:继承(扩展)、模块数据
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/11189252.html 一:继承 在不改变底层对象的时候添加新的功能——这是通过继承机制来实现的,作为在现有 ...