小学生都能看懂的题解 | #把数字翻译成字符串#
问题理解
我们要把一个由数字组成的字符串解码成字母。例如:
'1'解码成'a''2'解码成'b'- ...
'26'解码成'z'
给定一个数字字符串,比如 "12",我们想知道有多少种不同的方式把这个字符串解码成字母。
对于 "12",可以解码成:
'1'和'2'->'a'和'b'->"ab"'12'->'l'->"l"
所以 "12" 有 2 种解码方式。
解题思路
我们用动态规划来解决这个问题。想象一下我们有一个盒子,盒子里存放了解码的结果数量。我们一步一步地往盒子里加更多的结果。
-
初始化:
- 设定一个数组
dp,dp[i]代表前i个字符的解码方式数量。 dp[0]是 1,表示没有字符的情况有一种方式(什么都不做)。dp[1]是 1,如果第一个字符不是'0',它就有一种解码方式。
- 设定一个数组
-
逐步计算:
- 从第二个字符开始(即
i = 2),我们检查每个字符:- 如果当前字符单独可以解码(即它的值在
1到9之间),那么它的解码方式就等于前一个字符的解码方式(即dp[i] += dp[i-1])。 - 如果前两个字符组合在一起可以解码(即它的值在
10到26之间),那么它的解码方式就等于前两个字符的解码方式(即dp[i] += dp[i-2])。
- 如果当前字符单独可以解码(即它的值在
- 从第二个字符开始(即
-
最后结果:
- 当我们处理完所有字符后,
dp[n]就是整个字符串的解码方式数量。
- 当我们处理完所有字符后,
代码示例
以下是我们解决这个问题的代码:
public int solve(String nums) {
int n = nums.length();
// 如果字符串为空或第一个字符是'0',则没有解码方式
if (n == 0 || nums.charAt(0) == '0') return 0;
// 创建一个数组 dp,长度为 n + 1
int[] dp = new int[n + 1];
dp[0] = 1; // 空字符串的解码方式数量
dp[1] = 1; // 第一个字符的解码方式数量
for (int i = 2; i <= n; i++) {
// 取出当前字符
int oneDigit = Integer.parseInt(nums.substring(i - 1, i)); // 当前字符
// 取出当前和前一个字符
int twoDigits = Integer.parseInt(nums.substring(i - 2, i)); // 两个字符
// 如果当前字符可以解码
if (oneDigit >= 1 && oneDigit <= 9) {
dp[i] += dp[i - 1]; // 把前一个结果加到当前
}
// 如果前两个字符可以解码
if (twoDigits >= 10 && twoDigits <= 26) {
dp[i] += dp[i - 2]; // 把前两个结果加到当前
}
}
// 返回最后的解码方式数量
return dp[n];
}
逐行解释
-
public int solve(String nums):这是我们的方法,输入是一个数字字符串nums。 -
int n = nums.length();:获取字符串的长度。 -
检查特殊情况:
- 如果字符串为空或第一个字符是
'0',则直接返回0,因为没有解码方式。
- 如果字符串为空或第一个字符是
-
创建一个数组
dp:dp的大小是n + 1,用来存储每一步的解码方式数量。dp[0] = 1表示没有字符时的解码方式数量。dp[1] = 1表示第一个字符的解码方式数量。
-
for (int i = 2; i <= n; i++):从第二个字符开始逐步计算。 -
解析单个和两个字符:
oneDigit是当前字符。twoDigits是前两个字符组成的数字。
-
更新
dp[i]:- 如果单个字符可以解码,
dp[i]加上前一个结果。 - 如果两个字符可以解码,
dp[i]加上前两个结果。
- 如果单个字符可以解码,
-
返回结果:
- 最后返回
dp[n],就是整个字符串的解码方式数量。
- 最后返回
希望这篇文章对你有帮助👍。
#题解#小学生都能看懂的算法 文章被收录于专栏
主要面向小白的算法文章。以小学生都能看懂为目标而编写,顺便巩固下自己。


