​BM69 把数字翻译成字符串​

描述

有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。我们把一个字符串编码成一串数字,再考虑逆向编译成字符串。由于没有分隔符,数字编码成字母可能有多种编译结果,例如 11 既可以看做是两个 'a' 也可以看做是一个 'k' 。但 10 只可能是 'j' ,因为 0 不能编译成任何结果。现在给一串数字,返回有多少种可能的译码结果数据范围:字符串长度满足 [动态规划]BM69 把数字翻译成字符串-中等_动态规划进阶:空间复杂度 [动态规划]BM69 把数字翻译成字符串-中等_动态规划_02,时间复杂度 [动态规划]BM69 把数字翻译成字符串-中等_动态规划_02

示例1

输入:

"12"

复制返回值:

2

复制说明:

2种可能的译码结果(”ab” 或”l”)

示例2

输入:

"31717126241541717"

复制返回值:

192

复制说明:

192种可能的译码结果

题解

  1. 使用dp[i]表示到达索引i时解码的可能结果
  2. 初始条件:i = 0的时候有1种,字符长度为0有0种,为1有1种
  3. 状态方程:根据当前nums[i]和nums[i-1]的值确定具体的状态转移方程
  1. nums[i]=0,如果nums[i-1]不为1和2则为非法直接返回0,否则dp[i]=dp[i-1]
  2. nums[i]大于0小于7,如果nums[i-1]为1或者2,则nums[i] = nums[i-1] + nums[i-2],否则nums[i] = nums[i-1]
  3. nums[i]等于7、8、9中的一个,如果nums[i-1]为1或者2,则nums[i] = nums[i-1] + nums[i-2],否则nums[i] = nums[i-1]
  1. 遍历完字符串,返回dp[nums.size()-1]


代码如下:

#include <bits/stdc++.h>

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];
}