A message containing letters from A-Z
is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.
For example,
Given encoded message "12"
, it could be decoded as "AB"
(1 2) or "L"
(12).
The number of ways decoding "12"
is 2.
解题思路:
使用动态规划的思想。
(一)
初始想法可以建立一个数组,数组的每一位保存对应字符串的每一位可能出现的解码方式,例如:
字符串321321312;其对应的截止到每一位可能存在的解码方式种类为:
3 - 1种
32 - 1种
321 - 2种
3213 - 3种
32132 - 5种
....
所以得到解码方式数组为:
原字符串S: 3 2 1 3 2 1 3 1 2
解码种类数组A: 1 1 2 3 5 8 16 16 32
发现:
(1)如果当前字符可以和上一个字符组成二元字符,例如'1'和'2'组成'12',那么A[i] = A[i-1] + A[i-2];
很好理解,等于将'1' '2'分开的解码种类与将'12'合起来的解码种类之和;
(2)如果当前字符不能和上一个字符组成二元字符,那么A[i] = A[i-1];
(二)
因此,进一步的思路是,不需要建立一个数组,只需要保存i-2和i-1的解码种类数就可以了,分别用r1和r2表示;
如果当前字符可以组成二元字符,那么当前字符的次数 = r1 + r2;
如果不能,当前字符次数 = r1;
(三)
进一步发现,只用r1和r2两个变量就够了
(1)每次遇到可以组成二元字符的字符时,就更新r1,使r2等于旧的r1:
r1= r1 + r2;
r2 = r1;
(2)当不能组成二元字符时,r1不变,更新r2为r1;
(3)最终返回r1;
注意:
如果当前字符是'0',如果将'0'单独算,则不能产生任何解码数,即解码数为0;
代码:
int numDecodings(string s) {
if (!s.size() || s.front() == '') return ;
int r1 = , r2 = ; for (int i = ; i < s.size(); i++) {
if (s[i] == '') r1 = ; if (s[i - ] == '' || s[i - ] == '' && s[i] <= '') {
r1 = r2 + r1;
r2 = r1 - r2;
} else {
r2 = r1;
}
} return r1;
}