原题:
A message containing letters from A-Z
is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.
For example,
Given encoded message "12"
, it could be decoded as "AB"
(1 2) or "L"
(12).
The number of ways decoding "12"
is 2.
这个题应该我是用动态规划做的,思路:
1 对字符串的当前字母进行判断,如果是0,没有其他可能,这个decoding的可能性是0
2 如果字符是3-9,说明这个字母起码只能进行单独的解析,而且其可能性和substring(start+1 ,last)的可能性一样多(KEY)
3 如果字符是1或者2,需要考虑较多情况:
1) 如果进行单独的解析,即把1变成A,2变成B,这种可能性和substring(start+1 ,last)一样多
2)如果不单独进行解析,即是否和下一位进行两位数的解析(如把11变成K或把12变成L),如果是1,就不需要判断下一个元素了,因为从10到19都可以解析;如果是2,就需要看下一个元素是否是0-6,否则不能进行双位数的解析(即没有27-29),如果可以进行解析,这种可能性和substring(start+2 ,last)一样多(当然,需要判断start+2是否越界),然后把这两种情况加起来就是结果(KEY)了,如图1
图1
4 当前字符向后移动一位,继续1-3(KEY)
5 由于用到了递归,需要判定返回(KEY)的情况,其实由于是判断1位数和2位数,有两种返回情况:
1)字符串只有1位,只要是非0就有一种情况
2)字符串有2位,情况较多,<1>第一位是0,这个直接返回0 ; <2>第一位是1,如果第2位不是0,就有2种情况(如12);如果第2位是0,就只有一种情况(如10) <3>第1位是2 ,如果第2位是1-6,就有两种情况(如21);如果第2位是从7-9或0,就只有一种情况(如20,27) <4>其他情况返回0(如30),如图2:
6 为了防止超时,需要记录一下,我这里用record[i]代表当从第i个元素开始到string的最后的可能性,其实record[0]就是结果
代码( 376 ms):
public class Solution {
public int numDecodings(String s) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(s.length()==0) return 0;
int []record = new int[s.length()];
for (int i = 0 ;i < s.length(); i++){
record[i] = -1;
}
return numOfSubString(s , 0 , record);
}
public int numOfSubString(String s , int start , int [] record){
if(record[start]>=0) return record[start];
int result = 0;
if(start>s.length()-1){
record[start] = 0;
return 0;
}
if(s.charAt(start)=='0'){
record[start] = 0;
return 0;
}
else if(start==s.length()-1 ){
//判定的是最后一个元素,只要不是0,就是一种情况
record[start] = 1;
return 1;
}
else if(start==s.length()-2 ){
//判定的是倒数第二个元素
if( s.charAt(start)=='1'&& s.charAt(start+1)!='0' ){
//11-19都有两种情况
record[start] = 2;
return 2;
}
else if( s.charAt(start)=='2'&& s.charAt(start+1)>='1'&& s.charAt(start+1)<='6' ){
//21-26有两种情况
record[start] = 2;
return 2;
}
else if( s.charAt(start)>='3'&& s.charAt(start+1)=='0') {
//30,40..90为0种情况
record[start] = 0;
return 0;
}
//其余的为1种情况,只有10和20
record[start] = 1;
return 1;
}
if(s.charAt(start) >= '1' ){
//只要第一个元素不是0,就与substring(start+1,last)的情况数一致
result = numOfSubString(s , start+1, record);
//与后一个元素可以组成两位数,如10-26,就可以加上这种情况substring(start+2,last)
if( s.charAt(start) == '1'&& start+1 <= s.length()-1 ){
result += numOfSubString(s , start+2 ,record);
}
else if(s.charAt(start) == '2' && start+1 <= s.length()-1 && s.charAt(start+1)<='6'){
result += numOfSubString(s , start+2 ,record);
}
}
record[start] = result;
return result;
}
}