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.
s思路:
1. 一看这道题,还莫不清规律。没看提示的时候,发现可以用二分法。比如:”131121”从中间拆开,左边”111”有2种译码:”1,3,1”,”13,1”,右边也是”121”有3种:”1,2,1”,”12,1”,”1,21”,所以有2×3=6种;如果中间两个数可以组合在一起译码,比如”11”,那么:还需要把”13”和”21”的译码方式相乘,即:2×2=4.因此,总共有6+4=10种。
2. 经过提示,发现DP。不用二分,直接一个一个数的增加,看到目前为止有多少种译码方式。例如:
递推关系:if(第i个数和i-1可构成字母)则:dp[i]=dp[i-1]+dp[i-2]; 否则,dp[i]=dp[i-1]
//方法1:dp
class Solution {
public:
int numDecodings(string s) {
//
int n=s.size();
if(n==0) return 0;
vector<int> dp(n+1);
dp[0]=1;
for(int i=0;i<n;i++){
if(i>0&&s[i]=='0'&&(s[i-1]=='1'||s[i-1]=='2'))//处理0很麻烦!!!
dp[i+1]=dp[i-1];
else if(i>0&&(s[i-1]=='1'||s[i-1]=='2'&&s[i]<='6')){
dp[i+1]=dp[i]+dp[i-1];
}else if(s[i]>'0')
dp[i+1]=dp[i];
}
return dp[n];
}
};
//方法2:由于dp递推关系只用到了前两个结果,所以不用保存所有结果,只需要保存最近的两个结果!
class Solution {
public:
int numDecodings(string s) {
//
int n=s.size();
if(n==0) return 0;
int r1=(s[0]!='0'),r2=1;//r1代表s[0,i]的译码次数,r2代表s[0,i-1]的译码次数
for(int i=1;i<n;i++){
if(s[i]=='0') r1=0;
int tmp=r1;
if(s[i-1]=='1'||s[i-1]=='2'&&s[i]<='6')
r1=r1+r2;
r2=tmp;
}
return r1;
}
};