算法记录
LeetCode 题目:
一条包含字母 A-Z
的消息通过以下映射进行了 编码 :
'A' -> "1"
'B' -> "2"
...
'Z' -> "26"
复制代码
给你一个只含数字的 非空 字符串 s
,请计算并返回 解码 方法的 总数 。
说明
一、题目
要解码已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,"11106" 可以映射为:
- "AAJF" ,将消息分组为 (1 1 10 6)
- "KJF" ,将消息分组为 (11 10 6)
注意,消息不能分组为 (1 11 06) ,因为 "06" 不能映射为 "F" ,这是由于 "6" 和 "06" 在映射中并不等价。
二、分析
- 题目中的编码数量最多为两位数,也就是我们只需要考虑一个数以及他的后面一个数的情况就可以了。
- 如果说当前数和后面一个数组合的编码不在序列中,那么他们就不能进行合并,也就是只能单独的来分情况。
- 如果说当前数和后一个数能组成一个在序列中的编码数,也就是说他们可以拆分开来使用也可以合并使用,最后的种类就需要他们两种情况之和。
- 确定好分解的条件之后只需要注意边界条件的判断即可。
class Solution {
private Map<Integer, Integer> map = new HashMap();
public int numDecodings(String s) {
if(s.charAt(0) == '0') return 0;
return dfs(s.toCharArray(), 0);
}
public int dfs(char[] arrays, int start) {
if(start >= arrays.length) return 1;
if(arrays[start] == '0') return 0;
if(start == arrays.length - 1) return 1;
if(map.containsKey(start)) return map.get(start);
int ret = 0;
int cur = arrays[start] - '0', next = arrays[start + 1] - '0';
if(cur == 0) ret = 0;
else if(cur * 10 + next > 26 && next == 0) ret = 0;
else if(cur * 10 + next > 26) ret = dfs(arrays, start + 1);
else if(next == 0) ret = dfs(arrays, start + 2);
else ret = dfs(arrays, start + 1) + dfs(arrays, start + 2);
map.put(start, ret);
return ret;
}
}
复制代码
总结
问题拆解的能力。