解码方法
这道题目我考虑到了使用动态规划,但是考虑的不全面。
算法分析
分析:
- 本题利用动态规划解决,但是需要注意分情况讨论
- dp[i] 为str[0……i]的译码方法总数
- 分情况讨论:
- (极端情况)若s[i] = '0',那么若s[i-1] = '1' or '2',则dp[i] = dp[i-1];否则return 0
解释 10合并译码,20合并译码。【30、40等无法译码】
- 若s[i-1] = 1,则dp[i] = dp[i-1] + dp[i-2]
解释 因为译码最多是两两结合,我们合理往前推测两位。这种情况下有两种子情况。
- i-2 和 i-1 合并译码 dp[i-1]中方案 2. i-1 和 i合并译码,有dp[i-2]中方案。合计dp[i-1] + dp[i-2]中方案
- 若s[i-1] = 2 且 s[i]>'0'&&s[i] < '7',则dp同上
解释同上
- 其它情况不新增解码方法数
注意:具体写代码的时候要注意边界情况。
- (极端情况)若s[i] = '0',那么若s[i-1] = '1' or '2',则dp[i] = dp[i-1];否则return 0
class Solution {
public:
int numDecodings(string s) {
//首先排除特殊情况
int len = s.size();
if(s[0] == '0'){
return 0;
}
int num[len];
num[0] = 1;//初始化
for(int i=1;i<len;i++){
if(s[i] == '0'){//首先判断特殊条件
if(s[i-1] == '1' || s[i-1] == '2'){
num[i] = i==1?num[i-1]:num[i-2];//10(20),合并译码,不增加新的译码方法
}else{
return 0;//此时无法译码……3/0/5 0……
}
}else{
if(s[i-1] == '1'){
num[i] = i==1?num[i-1]+1:num[i-1] + num[i-2];
}else if(s[i-1] == '2' && s[i]>'0'&&s[i] < '7'){
num[i] = i==1?num[i-1]+1:num[i-1] + num[i-2];
}else{
num[i] = num[i-1]; //其余所有情况都是不新增解码方法
}
}
}
return num[len-1];
}
};
因为num[i] 仅仅可能与前两项有关,所以可以用单变量代替num[]数组,滚动变量。
class Solution {
public:
int numDecodings(string s) {
//首先排除特殊情况
int len = s.size();
if(s[0] == '0'){
return 0;
}
int pre,cur;
pre = cur = 1;
int temp;
for(int i=1;i<len;i++){
temp = cur;
if(s[i] == '0'){//首先判断特殊条件
if(s[i-1] == '1' || s[i-1] == '2'){
cur = pre;//10(20),合并译码,不增加新的译码方法
}else{
return 0;//此时无法译码……3/0/5 0……
}
}else{
if(s[i-1] == '1' || s[i-1] == '2' && s[i]>'0'&&s[i] < '7'){
cur = cur + pre;
}
}
pre = temp; //滚动临时变量
}
return cur;
}
};