题目链接
题目描述
问题描述
小M获得了一个任务,需要将数字翻译成字符串。翻译规则是:0对应"a",1对应"b",依此类推直到25对应"z"。一个数字可能有多种翻译方法。小M需要一个程序来计算一个数字有多少种不同的翻译方法。
例如:数字12258可以翻译成 "bccfi", "bwfi", "bczi", "mcfi" 和 "mzi",共5种方式。
测试样例
样例1:
输入:
num = 12258输出:5
样例2:
输入:
num = 1400112输出:6
样例3:
输入:
num = 2110101输出:10
样例4:
输入:
num = 25输出:2
样例5:
输入:
num = 1023输出:4
题目思路
很简单的线性动态规划
解释一下dp数组的含义
dp[i]表示前i个数字一共有多少种不同的翻译方法。那么,dp[n]就表示前n个数字一共有多少种不同的翻译方法,即为答案。
对于第i个数字,我们有两种决策:
1:单独翻译,所以dp[i] = dp[i-1]
2:与前面组合,这里要进行判断是否可以和前面进行组合,下面代码有详细的解释,所以dp[i] = dp[i-2]
dp【0】一定要初始化为1,为了防止第二个数字就可以和第一个数字翻译。
题解代码
// 省事直接用万能头文件
#include <bits/stdc++.h>
// 为了方便,使用了C++11的标准
using namespace std;
int solution(int num) {
// 定义一个字符串,用于存储数字的字符串表示
string str = to_string(num);
// 定义一个动态规划数组,用于存储每个数字的解码方式数量
vector<int> dp(str.length() + 1, 0);
// 初始化dp[0]和dp[1]
// 为了防止数组越界,dp[0]表示空字符串的解码方式数量,为1
dp[0] = 1;
// 为了方便计算,dp[1]表示第一个数字的解码方式数量,为1
dp[1] = 1;
// 遍历字符串中的每个数字
for (int i = 2; i <= str.length(); i++) {
// 取出当前数字和前一个数字
int cur = str[i - 1] - '0';
int pre = str[i - 2] - '0';
int num = pre * 10 + cur;
// 检查是否可以与前一个数字组成一个两位数,并且在10到25之间
if(num >= 10 && num <= 25) {
// 如果可以,当前数字的解码方式数量为前两个数字的解码方式数量之和
dp[i] = dp[i - 1] + dp[i - 2];
} else {
// 如果不可以,当前数字的解码方式数量为前一个数字的解码方式数量
dp[i] = dp[i - 1];
}
}
// 返回最后一个数字的解码方式数量
return dp[str.length()];
}
int main() {
// You can add more test cases here
std::cout << (solution(12258) == 5) << std::endl;
std::cout << (solution(1400112) == 6) << std::endl;
std::cout << (solution(2110101) == 10) << std::endl;
return 0;
}