题目
一条包含字母 A-Z
的消息通过以下方式进行了编码:
'A' -> 1
'B' -> 2
...
'Z' -> 26
给定一个只包含数字的 非空 字符串,请计算解码方法的总数。
题目数据保证答案肯定是一个 32 位的整数。
示例 1:
输入:"12"
输出:2
解释:它可以解码为 "AB"(1 2)或者 "L"(12)。
示例 2:
输入:"226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
示例 3:
输入:s = "0"
输出:0
示例 4:
输入:s = "1"
输出:1
示例 5:
输入:s = "2"
输出:1
提示:
1 <= s.length <= 100
s 只包含数字,并且可以包含前导零。
思路
这是一道递推的题目,我们依次遍历每个字符,那么对于每个字符,有这样两种情况:(为了方便描述,令 nums[i]
表示 0-i
对应的解码数量)
- 自己本身就是一个编码;那么
nums[i] = nums[i-1]
; - 与前一个字符组成一个编码;这种情况下,
nums[i] = nums[i-2]
;
所以 nums[i] = nums[i-1] + nums[i-2]
,当然这两种情况是否合法,需要具体讨论。
另外这道题有一个坑点,题目并不保证给定的编码是合法的,也就是在解码过程中发现变法不合法,要返回0;不合法的有以下几种情况:
- 001,包含前导0的;
- 1001,多个连续0的;
- 230,30不在1-26范围内;
具体见代码:
代码
class Solution {
public int numDecodings(String s) {
int n1 = 0, n2 = 1, ans = 0;
for (int i=0; i<s.length(); i++) {
int t = s.charAt(i) - '0';
if (t == 0) {
if (i > 0)
t += (s.charAt(i-1)-'0')*10;
if (t > 0 && t <= 26)
ans = n1;
else
return 0;
} else {
ans = n2;
if (i > 0 && s.charAt(i-1) != '0') {
t += (s.charAt(i-1)-'0')*10;
if (t <= 26)
ans += n1;
}
}
n1 = n2;
n2 = ans;
}
return ans;
}
}