题解:学而思编程 解码方法
【题目来源】
学而思编程:解码方法
【题目描述】
给出一个数字 \(n\),我们按照如下规则把它翻译为字符串:0 翻译成 "a" ,1 翻译成 "b",......,11 翻译成 "l",......,25 翻译成 "z"。一个数字可能有多个翻译。请编程计算一个数字有多少种不同的翻译方法。
例如102040有4种不同的翻译方法:分别是"bacaea", "bauea", "kcaea"和"kuea"。
【输入】
一行,一个整数 \(n\)
【输出】
一个整数,翻译方法数
【输入样例】
102040
【输出样例】
4
【核心思想】
-
问题分析:给定一个数字字符串 \(s\),每个数字可以单独翻译(0→a, 1→b, ..., 9→j),或者与前一个数字组合成两位数翻译(10→k, 11→l, ..., 25→z)。求不同的翻译方法总数。这是一个线性动态规划问题,类似于斐波那契数列的递推关系。
-
算法选择:
- 动态规划(DP):\(dp[i]\) 表示前 \(i\) 个字符的翻译方法数
- 状态转移:根据当前字符能否与前一个字符组合,决定转移方式
-
关键步骤:
- 将输入数字转为字符串 \(s\),下标从 \(1\) 开始
- 初始化:\(dp[0] = 1\)(空字符串有 \(1\) 种解码方式),\(dp[1] = 1\)(第一个字符单独解码)
- 状态转移(从 \(i = 2\) 到 \(n\)):
- 检查 \(s[i-1]\) 和 \(s[i]\) 能否组成有效两位数(\(10\) 到 \(25\)):
- 若 \(s[i-1] = '1'\):可以组成 \(10\)-\(19\),有效
- 若 \(s[i-1] = '2'\) 且 \(s[i] \leq '5'\):可以组成 \(20\)-\(25\),有效
- 若能组合:\(dp[i] = dp[i-1] + dp[i-2]\)
- \(dp[i-1]\):\(s[i]\) 单独解码的方法数
- \(dp[i-2]\):\(s[i-1]\) 和 \(s[i]\) 组合解码的方法数
- 若不能组合:\(dp[i] = dp[i-1]\)(只能单独解码)
- 检查 \(s[i-1]\) 和 \(s[i]\) 能否组成有效两位数(\(10\) 到 \(25\)):
- 输出 \(dp[n]\) 作为答案
-
时间/空间复杂度:
- 时间复杂度:\(O(n)\),只需遍历字符串一次
- 空间复杂度:\(O(n)\),使用 \(dp\) 数组(可优化至 \(O(1)\),只保留 \(dp[i-1]\) 和 \(dp[i-2]\))
-
线性DP与类斐波那契递推的核心思想:
- 最优子结构:前 \(i\) 个字符的解码数只与前 \(i-1\) 和 \(i-2\) 个字符有关
- 状态转移分情况:根据当前字符能否与前一个组合,决定是单步走还是双步走
- 边界条件处理:\(dp[0]\) 和 \(dp[1]\) 的初始化是递推的基础
- 适用于字符串解码、爬楼梯、分割整数等组合计数问题
【算法标签】
线性DP-一维
【代码详解】
#include<iostream>
#include<algorithm>
using namespace std;
string s; // 输入的数字字符串
int n, dp[55]; // n: 字符串长度,dp: 动态规划数组
int main()
{
cin >> s; // 读入数字字符串
n = s.size(); // 获取字符串长度
s = ' ' + s; // 在字符串前加一个空格,使下标从1开始
dp[0] = dp[1] = 1; // 初始化动态规划数组
// dp[0] = 1: 空字符串有1种解码方式
// dp[1] = 1: 第一个字符单独解码有1种方式
for (int i = 2; i <= n; i++)
{
// 检查前两个字符是否能组成一个有效的两位数
// 条件1: 前一个字符是'1',则当前字符可以是0-9
// 条件2: 前一个字符是'2'且当前字符小于等于'5',则组成的数字是20-25
if (s[i - 1] == '1' || s[i - 1] == '2' && s[i] <= '5')
{
// 如果前两个字符能组成有效数字,则有两种解码方式:
// 1. 当前字符单独解码:dp[i-1]种方式
// 2. 前两个字符一起解码:dp[i-2]种方式
dp[i] = dp[i - 1] + dp[i - 2];
}
else
{
// 如果前两个字符不能组成有效数字,则当前字符必须单独解码
dp[i] = dp[i - 1];
}
}
cout << dp[n]; // 输出整个字符串的解码方式总数
return 0;
}
【运行结果】
102040
4
浙公网安备 33010602011771号