https://i-blog.csdnimg.cn/blog_migrate/8bd0239a44d2f6ead63870d5030a2877.png
一条包含字母 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) 。
动规首先就是要分解子问题嘛
首先捏,从宏观上来看,先不管各种限制,进行如下分析:
字符串长度为1时,假设字符串是“1”,F(1)= 1;
字符串长度为2时,假设字符串是“12”,F(2)= 2;情况有:(1,2)(12)
字符串长度为3时,假设字符串是“123”,F(3)= F(2) + F(1);
为什么是这样呢?
情况一:“3” 和 “12”的情况,“12”的种类正是F(2)
情况二:“23” 与 “1”的情况,“1”的种类正是F(1)
有些人就奇怪,为什么不算”23“的种类,来看一下”23“可以分成(2,3)和(23),但是”2,3“这种情况在情况一中已有体现(情况一已把3单独拆开),情况二这里再算的话就会有重复。
以此类推,F(n) = F(n - 1) + F(n -2 );
接下来看到细节:
分析情况一:解码方法数为:最后一个数字提取出来,这个数字之前的字符串的解码方法数。
提取数字前的字符串解码方法数F(n - 1)不多bb,分析一下提取出来的数字。
根据题意可知(1~26)表示A~Z,其中单个数字范围就是1~9了
所以可知提取出来的数字是0时,情况一为0,否则才是F(n - 1);
分析情况二:解码方法数为:最后两个数字提取出来,这俩数字之前的字符串的解码方法数。
提取数字前的字符串解码方法数F(n - 2)不多bb,分析一下提取出来的俩数字。
根据题意可知(1~26)表示A~Z,其中单个数字范围就是10~27了
所以大于27或小于10情况二直接为0,否则是F(n - 2);
代码如下:
public int numDecodings(String s) {
if (s == null)
return 0;
int[] ints = new int[s.length() + 1];
ints[0] = 1;
char[] cs = s.toCharArray();
if (ints.length > 1)
ints[1] = cs[0] == '0' ? 0 : 1;
for (int i = 2; i < ints.length; i++){
if (cs[i - 2] != '0' && (cs[i - 2] == '1' || cs[i - 2] == '2' && cs[i - 1] < '7'))
ints[i] += ints[i - 2];
if (cs[i - 1] != '0')
ints[i] += ints[i - 1];
}
return ints[ints.length - 1];
}