一条包含字母 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).s的首部不能是0!!
2).中间部分可以是0但是 它的前面那个数字必须是1 或者2(以上两点需要在开始计算前 先遍历一遍)
3).计算过程中如果遇到0怎么办???(我们需要把这个0与他前面那个数字x(如果步骤1和步骤2做过了 只可能是1或者2)绑定在一起 )
4).绑定的那个 x不能再与(x之前那个数字组合在一起 假设前面那个数字存在的话) ps:::比如 1220 (“20”是要在一起的 同时22虽然我们可以解码出来一个字符 但是 20已经被绑住一起了!!!)
5).对于 一个串 s 他的解码个数是不是直接由 (前面s.size()-1 个推倒出来 的 比如s=123 假设我已经知道 “23”的解码个数为k 能否直接推倒 出 “123”的个数)????? ps::我们知道 这些数字只要组合起来<=26 是可以看成一个数的 所以 从后往前遍历到“1”的时候 其实 由两部分组成
第一 把“1”单独看 s 就是“23”的解码个数
第二把“12”单独看 s就是“3”的解码个数(注意 如果 s=1203 这个时候 只有第一种情况 你是不能把 12 合在一起看的 2必须要和0绑定在一起 也就是 4)中我们提到的情况)
于是 s(n)就等于以上两种情况的个数和(以此类推)
int numDecodings(string s) {
for (int i = 0; i <= s.size() - 1; i++){
if (s[i] == '0'){
if (i == 0) return 0;
else {
if (s[i - 1] == '1' || s[i - 1] == '2')continue;
else return 0;
}
}
}
vector total(s.size()+1);
for (int i = 0; i <= total.size() - 1; i++)total[i] = 0;
total[total.size() - 1] = 1;
for (int end = s.size() - 1;end >= 0; end--){
if (end == s.size() - 1) total[end] = 1;
else{
if (s[end] == '0'){
total[end] = total[end + 1];
}
else{
if (s[end + 1] == '0') total[end] = total[end + 1];
else {//都不是0
if (end + 2 <= s.size() - 1){
if (s[end + 2] == '0') { total[end] = total[end + 1]; continue; }
}
string tmp = s.substr(end , 2);
int t = atoi(tmp.c_str());
if (t <= 26) total[end] = total[end + 2] + total[end + 1];
else total[end] = total[end + 1];
}
}
}
}
return total[0];
}