算法原理及代码
tips: 经验+题目要求。以i位置为结尾,。。。
dp[i]: 以i位置为结尾时,解码方法的总数
tips: 用之前或之后的状态,推导出dp[i]的值。根据最近的一步,来划分问题
i下标位置为结尾时:
即:dp[i] = dp[i-1] + dp[i-2],当成功时才加上对应的
tips: 保证填表的时候不越界。因此需要初始化0和1位置
dp[0]=1或0; //s[0]可否解码
dp[1] = 0或1或2; //s[1]可否解码、s[0]s[1]可否解码
从左往右(----->)
题目要求是整个字符串的解码方案数
即:return dp[n-1];
代码:
class Solution {
public:
int numDecodings(string s) {
//1.创建dp表
//2.初始化
//3.填表
//4.返回值
int n = s.size();
vector dp(n);
if(s[0] != '0') dp[0] = 1;
if(n == 1) return dp[0];
if(s[1] != '0') dp[1] = dp[0];
int t = (s[0] - '0') * 10 + s[1] - '0';
if(t >= 10 && t <= 26) dp[1]++;
for(int i = 2; i < n; ++i)
{
if(s[i] != '0') dp[i] += dp[i - 1];
int t = (s[i - 1] - '0') * 10 + s[i] - '0';
if(t >= 10 && t <= 26) dp[i] += dp[i - 2];
}
return dp[n-1];
}
};
小技巧 处理边界问题以及初始问题的技巧
对于上述题解中初始化
dp[1]
的操作比较繁琐。
在最前面增加一个虚拟节点,新dp[2] 需要 dp[0],dp[1]
注意事项:
如果s[0]s[1]能够一起解码成功,则新dp[2] = + dp[0]
dp[0] = 1
,保证填2的时候是正确的
class Solution {
public:
int numDecodings(string s) {
//1.创建dp表
//2.初始化
//3.填表
//4.返回值
int n = s.size();
vector dp(n+1);
//注意:下标的映射关系
dp[0] = 1;
if(s[0] != '0') dp[1] = 1;
for(int i = 2; i <= n; ++i)
{
if(s[i - 1] != '0') dp[i] = dp[i - 1];
int t = (s[i - 2] - '0') * 10 + s[i - 1] - '0';
if(t >= 10 && t <= 26) dp[i] += dp[i - 2];
}
return dp[n];
}
};
观看~~