给定一个只包含数字的非空字符串,请计算解码方法的总数
(题目来源:力扣网)
解码方法:
'A' -> 1
'B' -> 2 ...
'Z' -> 26
给定一个只包含数字的非空字符串,请计算解码方法的总数。
示例 1:
输入: "12"
输出: 2
解释: 它可以解码为 "AB"(1 2)或者 "L"(12)。
示例 2:
分析过程:
1.找到规律(不含特殊情况):
- 1 位数字 :1种
- 2 位数字 :1+1种 例:23
- 3 位数字 : 2+1种 例:666 161 116
- 4 位数字 :3+2种 例:16 12 1113 1116
- 5 位数字 :5+3种 例:13214 12115 12011 12213
- 6 位数字 :8+5种 例:112113
- n 位数字 :f(n-1)+f(n-2)种
2. 在上面基础上进一步考虑
特殊:
2.1、0开头,连续0,直接返回0次
2.2、从第二位数字开始遍历字符串 - 当前数字是0且0之前的数字大于3,直接返回0次。若0之前数字是1或2,绑定两个数字,如果字符串长度为2,返回1,否则当前次数=当前数字的前两位的次数
- 当前数字不是0
- 前一位数字为0,该位数字前一位为0,前一位肯定组合了并减去次数,返回上一位数字次数就行
- 前一位数字不为0且和前一位数字组合大于26,则当前次数=当前前一位数字的次数。 前一位数字不为0且和前一位数字组合小于等于26的话:len=2,返回2,len>2的话:当前次数=当前前一位数字的次数++当前前两位数字的次数。
解决方法
输入: "226"
输出: 3
解释: 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
public static int numDecodings(String s) {
//以0开头的字符串或两个0连续出现直接返回0,无解
if(s.charAt(0)=='0'||s.contains("00")) return 0;
//创建一个存储结果的数组
int[] m=new int[s.length()];
m[0]=1;//单独一个不是0的数字(1~9)必合法,第一位次数:0
for(int i=1;i<s.length();i++){
if(s.charAt(i)=='0'){//当前数字为0
if(s.charAt(i-1)>'2') return 0;//0前头不是1,也不是2,无法分开,也无法组合,直接返回0
else m[i]=i-2<0?1:m[i-2];//10或者20的情况,只能把10,20组合在一起解码
}else{//当前数字不为0
if(s.charAt(i-1)=='0') m[i]=m[i-1];//该位数字前一位为0,前一位肯定组合了并减去次数,返回上一级次数就行
else{//前面数字也不是0
//只要满足1...26之间就合法,如“11”可解码成2种
if(Integer.parseInt(s.substring(i-1,i+1))<=26) m[i]=(i-2)<0?2:(m[i-1]+m[i-2]);
else m[i]=m[i-1];//不合法则返回上一级的次数,因为这个数不能组合,如“138”,只有1种解法
}
}
}
return m[s.length()-1];
}