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).解法
解法(动态规划):
设数组dp[i]表示字符串s第i个字符之前(包括第i位)的所有有效编码组合数。dp从1开始表述。所以dp的长度是s.length() + 1.
有效编码的规则:一位数情况下不为零;两位数情况下在1-26之间。
另初始位dp[0] = 1 ;dp[1]则表示如果只考虑当前字符串的第一个字符,能产生的有效编码组合数。所以这里有两种可能性:s的第一位为零,或者不为零。显然,如果该位为零,则当前字符不是有效编码,所以dp[1] = 0; 反之,当前字符是有效编码,故dp[1] = 1.
接下来依次看s中剩下的字符。以123举例:
s[0] = 1; s[1] = 2; s[2] = 3 ;
dp[0] = 1;
计算dp[1]: 因为s[0] =1,它及它之前只有1一种组合方式,所以dp[1] = 1 ;
计算dp[2]: 因为s[1] =2, 它自身可以和s[0]单独形成有效编码,所以dp[2] = 1; 这里没完,因为s[1]还可以和它的前一位s[0]拼成一个有效编码12,所以实际可以有两种组合方式,故dp[2] = dp[2] + dp[1] = 2 ;
计算dp[3]: 因为s[2] =3, 它自身可以和s[0],s[1]单独形成有效编码,所以dp[3] = 1; 除此以外,s[2]还可以和它之前的s[1]一同组合,所以dp[3]还应该加上dp[2]的组合数,故dp[3] = dp[3] + dp[2] = 3;
计算到这里,我们可以推断出一个公式:dp[i] = dp[i] + dp[i-1] (i>=2).
但是这还没完,因为还有一些例外情况,比如当前第i个字符是0时,它自身无法独立形成有效编码,只能依附于它之前的字符一同形成有效编码,所以这个时候dp[i]只能等于dp[i] + dp[i-2],跳过dp[i] + dp[i-1].
代码:
public static int numDecodings(String s) {
int dp[] = new int[s.length()+1] ;
dp[0] = 1 ;
if(isValid(s.substring(0,1))) { // check s[0]
dp[1] = 1 ;
}else {
dp[1] = 0 ;
}
for(int i=2; i<=s.length(); i++) {
if(isValid(s.substring(i-1,i))) { // check s[i]
dp[i] += dp[i-1] ;
}
if(isValid(s.substring(i-2,i))) { // check s[i-1:i]
dp[i] += dp[i-2] ;
}
}
return dp[s.length()] ;
}
public static boolean isValid(String s){
if (s.length() == 1 && s.charAt(0) != '0')
return true;
if(s.length() == 2 && s.charAt(0) == '1' && s.charAt(1) <= '9') {
return true ;
}
if(s.length() == 2 && s.charAt(0) == '2' && s.charAt(1) <= '6') {
return true ;
}
return false ;
}
来源:CSDN
作者:yexianyi
链接:https://blog.csdn.net/yexianyi/article/details/103456711