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.
class Solution { bool judge(int i) { return i > 0 && i<3; } bool judge(int i,int j) { int t = i*10 + j; if(t>26 || t <=10) return false; return true; } public: int numDecodings(string s) { int n = s.size(); int a[n]; for(int i = 0;i<n;++i) { a[i] = s[i] - '0'; } if(n == 0) return 0; // 第一个数是0 if(a[0] == 0) return 0; if(n == 1) return 1; int dp[s.size()]; dp[0] = 1; if (a[1] != 0) dp[1] = judge(a[0],a[1]) ? 2 : 1; else{ if(a[0]<=0 || a[0] > 2) return 0; else dp[1] = 1; } if (n==2) return dp[1]; for(int i = 2; i<n; ++i) { if (a[i] != 0) dp[i] = dp[i-1] + (judge(a[i-1],a[i]) ? dp[i-2] : 0); else if(a[i-1]<=0 || a[i-1] > 2) return 0; else dp[i] = dp[i-2]; } return dp[n-1]; } };
开始时候没有考虑到里面会出现0,然后就很傻比的提交了。。。
可以定义 dp[n],a[n]
伪代码如下,
if a[i] == 0
if a[i-1] 大于0小于3// 这样a[i-1]和a[i]可以构成一个字母
dp[i] = dp[i-2] // 这样的话,种类数只能和dp[i-2]相等,种类数没有增加
else
dp[i] = 0// 其他情况下都不合法
else
如果a[i-1]<=0,大于二
dp[i] = dp[i-1]// 新增的字母只能是一种情况
else
dp[i] = dp[i-1]+dp[i-2]// 把新增的字母当一种情况,还可以吧新增的字母和旧字母当成一种情况
看一下大哥的答案
int numDecodings(string s) { if (!s.size() || s.front() == '0') return 0; // r2: decode ways of s[i-2] , r1: decode ways of s[i-1] int r1 = 1, r2 = 1; for (int i = 1; i < s.size(); i++) { // zero voids ways of the last because zero cannot be used separately if (s[i] == '0') r1 = 0; // possible two-digit letter, so new r1 is sum of both while new r2 is the old r1 if (s[i - 1] == '1' || s[i - 1] == '2' && s[i] <= '6') { r1 = r2 + r1; r2 = r1 - r2; } // one-digit letter, no new way added else { r2 = r1; } } return r1; }
这个就简介明了了很多。空间是O(1)的,因为只需要储存前两个的值。