解题思路:
动态规划问题(dp)。
一个字母对应了唯一的编码,所以正着编码一定是唯一的。
但是反过来就不唯一了。
我们要找一共有多少种方法反编码
dp分析:
考虑集合的表示:
f[i]一维集合,代表着前i个数字一共有多少种反编码方式
考虑状态的计算:
编码数字一共只有1到26,所以编码只有一位和两位。
- 如果是一位的话,数字介于1~9之间。没有0!!
- 如果是两位的话,数字介于10~26之间
从前遍历,当前第i位。
这样我们就可以分出两种情况:
- 如果当前位s[i](字符串的第i个,字符串用s表示)大于0且小于10,那么当前为可以单独表示一个字母的编码。前i位的编码方式要加上f[i-1]。(当前位唯一确定,组成方式就是前i-1个的组成方式)。
- 计算出s[i - 1] * 10 + s[i]的数值,即当前位和前一位表示的数字。如果在10~26之间,代表这两个数字也可以反编码出来。前i位的编码方式加上f[i-2]。(s[i-1]和s[i]唯一确定了,组成方式是前i-2个的组成方式)
代码实现:
class Solution {
public int numDecodings(String s) {
int len = s.length();
s = " " + s;
int[] f = new int[len + 10];
// 没有数字对应空字符串,为1
f[0] = 1;
for (int i = 1; i <= len; i ++ ) {
if(s.charAt(i) >= '1' && s.charAt(i) <= '9') f[i] += f[i - 1];
int t = (int)(s.charAt(i - 1) - '0') * 10 + (int)(s.charAt(i) - '0');
if(t >= 10 && t <= 26) f[i] += f[i - 2];
}
return f[len];
}
}