题目描述
一条包含字母 A-Z 的消息通过以下方式进行了编码:
'A' -> 1
'B' -> 2
...
'Z' -> 26
给定一个只包含数字的非空字符串,请计算解码方法的总数。
示例:
输入: "12"
输出: 2
解释: 它可以解码为 "AB"(1 2)或者 "L"(12)。
解题思路
状态转移方程: d[i] = dp[i+1] + g(i,i+1) * dp[i+2] => 可以看出需要从后往前遍历。
注:dp后还可以“空间压缩”到常数级别的空间复杂度,因为每次的 dp[i] 只与 dp[i+1] 和 dp[i+2] 有关,因此我们可以用两个变量来记录并不断更新 dp[i+1] 和 dp[i+2] 。此外,在做动态规划题目的时候,要特别注意“遍历方向”的问题,要保证我们的算法是“自底向上”求解的。(由小到大)
参考代码
注:本题从1开始编码,需要一些特判才行。可直接参考《剑指offer》第46题处的代码。
class Solution {
public:
int numDecodings(string str) {
int length = str.length();
if(length == 0)
return 0;
vector<int> dp(length, 0);
for(int i = length-1; i >= 0; i--){
int temp = 0;
if(i == length-1 && (str[i] - '0') > 0){ // 注意要求(str[i] - '0') > 0 特判
dp[i] = 1;
continue;
}
if(i <= length-2 && (str[i] - '0') > 0){ // 注意要求(str[i] - '0') > 0
if((str[i] - '0') == 0) // 若当前的位置的数字为0,这是无法有效解码的。特判
continue;
temp += dp[i+1];
int twoDigitsNum = 10 * (str[i] - '0') + (str[i+1] - '0');
if(twoDigitsNum >= 10 && twoDigitsNum <= 26){
if(i == length-2)
temp += 1;
else
temp += dp[i+2];
}
}
dp[i] = temp;
}
return dp[0];
}
};
本文详细解析了一种基于数字的编码解码算法,该算法将字母A-Z转换为1-26的数字,并探讨了如何计算给定数字串的可能解码方法总数。通过动态规划方法,介绍了状态转移方程及其应用,特别强调了遍历方向的重要性。
531

被折叠的 条评论
为什么被折叠?



