描述
有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。我们把一个字符串编码成一串数字,再考虑逆向编译成字符串。由于没有分隔符,数字编码成字母可能有多种编译结果,例如 11 既可以看做是两个 'a' 也可以看做是一个 'k' 。但 10 只可能是 'j' ,因为 0 不能编译成任何结果。现在给一串数字,返回有多少种可能的译码结果数据范围:字符串长度满足 进阶:空间复杂度 ,时间复杂度
示例1
输入:
"12"
复制返回值:
2
复制说明:
2种可能的译码结果(”ab” 或”l”)
示例2
输入:
"31717126241541717"
复制返回值:
192
复制说明:
192种可能的译码结果
题解
- 使用dp[i]表示到达索引i时解码的可能结果
- 初始条件:i = 0的时候有1种,字符长度为0有0种,为1有1种
- 状态方程:根据当前nums[i]和nums[i-1]的值确定具体的状态转移方程
- nums[i]=0,如果nums[i-1]不为1和2则为非法直接返回0,否则dp[i]=dp[i-1]
- nums[i]大于0小于7,如果nums[i-1]为1或者2,则nums[i] = nums[i-1] + nums[i-2],否则nums[i] = nums[i-1]
- nums[i]等于7、8、9中的一个,如果nums[i-1]为1或者2,则nums[i] = nums[i-1] + nums[i-2],否则nums[i] = nums[i-1]
- 遍历完字符串,返回dp[nums.size()-1]
代码如下:
using namespace std;
int solve(string nums)
{
if (nums.size() <= 1)
{
return nums.size();
}
std::vector<int> dp(nums.size() + 1, 1); // dp[i]表示[0,i]的字符串的翻译方法数
if (nums[0] == '0')
{
return 0;
}
for (int i = 1; i < nums.size(); ++i)
{
auto x = nums[i];
auto pre = nums[i - 1];
if (x == '0') // 等于0,前面一个元素一定是1或者2,因此组合方法数不变
{
if (pre != '1' && pre != '2')
{
return 0;
}
dp[i] = dp[i - 1];
}
else if (x >= '1' && x <= '6')
{
if (pre == '1' || pre == '2')
{
dp[i] = dp[i - 1] + dp[i - 2];
}
else
{
dp[i] = dp[i - 1];
}
}
else if (x >= '7' && x <= '9')
{
if (pre == '1')
{
dp[i] = dp[i - 1] + dp[i - 2];
}
else
{
dp[i] = dp[i - 1];
}
}
}
return dp[nums.size() - 1];
}