91. Decode Ways
原题目:
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.
题解:
这道题需要我们求一个由数字组成的字符串可以有多少种编码方式。
可以用动态规划来解这个问题,定义状态f(n)为“从开始到第i个字符组成的子串能够有多少种编码方式”。假设要解码的字符串为s,可以推断出这样的规律:
- 如果s[i]可以解码成单独的一个字母,也就是说s[i]是不为0的数字,那f(n)就等于f(n-1)(相当于前n-1个字符都按照特定的方式解码了,那最后一个字符也就固定了)
- 如果s[i-1]与s[i]组成的双位数字可以解码为单独的一个字母,也就是他们组成的双位数大于0且小于27,那f(n)就等于f(n-2)(相当于前n-2个字符都按照特定的方式解码了,最后两位数当成是一个固定的组合)
- 如果同时存在上述的两种情况,那f(n) = f(n-1) + f(n-2)
- 如果情况1和2都不能被满足,意味着这个字符串存在不能被解码的部分(例如“1280”中“80”无论拆开还是拼在一起都不能成功解码),返回0
f(n)的初始状态为f(0)=1,但一旦开头字符为‘0’(无法解码),就返回0。若是字符串长度为1,且开头字符不为‘0’,就返回1。
代码:
class Solution { public: bool isValid(char a) { return a-'0' > 0; } bool isValid(char a, char b) { return a=='1' || (a == '2' && b < '7'); } int numDecodings(string s) { int n = s.size(); int f1 = 1; int f2 = 1; int res = 0; if(!isValid(s[0])) return 0; else if(n==1) return 1; for(int i = 1 ; i < n ;i++) { if(isValid(s[i]) && isValid(s[i-1],s[i])) res = (f1+f2); else if(isValid(s[i]) && !isValid(s[i-1],s[i])) res = f1; else if(!isValid(s[i]) && isValid(s[i-1],s[i])) res = f2; else return 0; f2 = f1; f1 = res; } return res; } };