一条包含字母 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) 。
思路:DP问题,当前位置(个位)与前一个位置(十位)上的两个数字刚好组成两位数,这两位数决定了递推方程:
代码:
1 class Solution { 2 public: 3 int numDecodings(string s) { 4 //F(m) = F(m-1) + F(m-2) 5 int length = s.length(); 6 if(length == 0) return length; 7 if(length == 1) { 8 if(s[0] == '0') return 0; 9 else return 1; 10 } 11 int m = 1,n = 2; 12 int num = (s[1] -'0' + 0)+ (s[0] -'0' + 0) * 10; 13 if(num < 10 || (num % 10 == 0 && num / 10 > 2)) { 14 return 0; 15 } else if (num == 10 || num == 20 || num > 26) { 16 n = 1; 17 } 18 if((s[0] == '1' || (s[0] == '2' && (s[1] -'0' + 0) < 7)) && s[1] != '0') n = 2; 19 for(int i = 2 ;i < length ;++i) { 20 int num = (s[i] -'0' + 0)+ (s[i - 1] -'0' + 0) * 10; 21 if(num == 0 || (num % 10 == 0 && num / 10 > 2)) { 22 return 0; 23 } else if (num < 10 || num > 26) { 24 m = n; 25 } 26 else if((10 < num && num < 20) || (20 < num && num <= 26)) { 27 n = m + n; 28 m = n - m; 29 } else if(num == 10 || num == 20){ 30 n = m + n; 31 m = n - m; 32 n = n - m; 33 } 34 } 35 return n; 36 } 37 };
后记:动态规划的解法,时间复杂度O(n),空间复杂度O(1),感觉这两点都没啥可优化的了。但是感觉代码写的有点丑,可以整合下。
精简后的代码:
1 class Solution { 2 public: 3 int numDecodings(string s) { 4 if(s[0] == '0') return 0; 5 int pre = 1,cur = 1; 6 int length = s.length(); 7 for(int i = 1;i < length ;++i) { 8 int temp = cur; 9 if(s[i] == '0') { 10 if(s[i - 1] == '2' || s[i - 1] == '1') cur = pre; 11 else return 0; 12 } else if(s[i - 1] == '1' || (s[i-1] == '2' && s[i] < '7' && s[i] > '0')) { 13 cur = pre + cur; 14 } 15 pre = temp; 16 } 17 return cur; 18 } 19 };
在此感谢作者:pris_bupt
链接:https://leetcode-cn.com/problems/decode-ways/solution/c-wo-ren-wei-hen-jian-dan-zhi-guan-de-jie-fa-by-pr/