【Leetcode】91.解码方法

91.解码方法

题目

一条包含字母 A-Z 的消息通过以下方式进行了编码:

'A' -> 1
'B' -> 2
...
'Z' -> 26

给定一个只包含数字的非空字符串,请计算解码方法的总数。

示例 1:
输入: "12"
输出: 2
解释: 它可以解码为 "AB"(1 2)或者 "L"(12)。

示例 2:
输入: "226"
输出: 3
解释: 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。

方法(动态规划)

此题和70.爬楼梯这道题相似。爬楼梯要求每次只能爬一个台阶或两个台阶,所以爬n层台阶的爬法是爬n-1层台阶和爬n-2层台阶的爬法之和。而对于此题,一个字符既可以单独解码(例如:’1’ -> A),又可以和它的前一个字符共同解码(例如:’26’ -> Z)。

设dp[i]表示字符串前i个字符组成的子串s[0…i-1]的解码方法个数。于是从整体逻辑上而言:dp[i] = dp[i-1] + dp[i-2](和爬楼梯一样)
但本题比爬楼梯复杂在如下两点:

  • 对”0”的判断:0不能单独进行解码
  • 对两个字符组合的判断:只有当1<=s[i-1…i]<=26,这两个字符才可以一起解码

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public int numDecodings(String s) {
if(s == null || s.length() == 0)
return 0;
//合法的编码第一位不可能是0
if(s.charAt(0) == '0')
return 0;
//dp[i]为s中前i个字符的解码方法个数
int[] dp = new int[s.length() + 1];
//Base Case
dp[0] = 1;
dp[1] = s.charAt(0) == '0' ? 0 : 1;
for(int i = 2; i <= s.length(); i++){
//one为单个位解码所表示的数字,two为两位一起解码所表示的数字
int one = Integer.valueOf(s.substring(i - 1, i));
int two = Integer.valueOf(s.substring(i - 2, i));
//单个位能解码的前提是:这个位上不是0
if(one != 0)
dp[i] += dp[i - 1];
//两个位能一起解码的前提是:两个位所表示的数字小于26并且第一个位不能是0
if(s.charAt(i - 2) != '0' && two <= 26)
dp[i] += dp[i - 2];
}
return dp[s.length()];
}