A message containing letters from A-Z
is being encoded to numbers using the following mapping:git
'A' -> 1 'B' -> 2 ... 'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.app
For example,
Given encoded message "12"
, it could be decoded as "AB"
(1 2) or "L"
(12).post
The number of ways decoding "12"
is 2.spa
这道题一开始想用backtracking构造出全部可能的decoding ways,而后统计个数,可是后来发现这样的解法不管是空间复杂度仍是时间复杂度以及实现的难度都不太理想,必定还有更好的解决办法,没错,那就是动态规划了。翻译
咱们能够构造一个用于dp的vector,大小为输入string长度+1。其中第[0]个元素值为1,视为边界值,而后剩下的部分能够和输入string的每一个字符都一一对应起来,其含义就是到该处时有多少种decoding方法。可想而知,第一个字符只要不是'0',就必定能够翻译,所以dp[1] = 1。code
那么如何构造状态转移方程呢?假设咱们处理到了s[i]的位置,那么首先单个s[i]的字符是能够翻译的,若是只翻译单个s[i],那么翻译的种类有dp[i]种。若s[i-1]与s[i]构成的字符串其值是小于等于26的,那么还能够再有dp[i-1]种翻译方法。总共dp[i]+dp[i-1]种(即到s[i-2]处有多少种翻译方法,结合上s[i-1,i];以及到s[i-1]有多少种翻译方法,结合上s[i])。blog
若是s[i-1]与s[i]构成的字符串其值大于26,那么显然就只能和s[i-1]处的翻译方法数量同样了。字符串
另外还有一个特殊状况,即s[i]=0,由于单个0是没有办法翻译的,也就是说此时若是按照dp[i]的翻译方式(翻译到s[i-1],以后的字符串将以0打头)是不可行的,因此要将dp[i]赋值成0。string
最后,实际上每次在进行状态转移时,咱们最多只须要获取前两个状态,所以这里的空间复杂度还能够进一步从O(n)缩小到O(1),这里就不进一步展开了。上代码:it
class Solution { public: int numDecodings(string s) { int size = s.length(); if (size <= 0 || s[0] == '0') { return 0; } vector<int> dp(size + 1, 0); dp[0] = dp[1] = 1; for (int i = 1; i < size; ++i) { if (s[i] == '0') { dp[i] = 0; } if (s[i - 1] == '1' || s[i - 1] <= '2' && s[i] <= '6') { dp[i + 1] = dp[i] + dp[i - 1]; } else { dp[i + 1] = dp[i]; } } return dp[size]; } };