返回
让编码逆风翻盘:解密LeetCode 91:解码方法的代码世界
闲谈
2023-10-18 06:42:06
问题背景
LeetCode 91:解码方法题干:
给你一个只包含数字的字符串 s,其中每个数字可以映射到一个字母。例如,数字 '2' 可以映射到字母 'a'、'b' 或 'c'。
请你找出给定字符串有多少种不同的解码方法。
示例:
输入:s = "12"
输出:2
解释:它可以解码成 "ab"(1 对应 "a",2 对应 "b")或者 "l"(12 对应 "l")。
输入:s = "226"
输出:3
解释:它可以解码成 "aaa"、"aab" 和 "lc"。
算法原理
为了求解 LeetCode 91 的问题,我们可以使用动态规划的思想。动态规划的核心在于将原问题分解为一系列子问题,然后依次解决这些子问题,最终得到原问题的解。
对于解码方法算法,我们可以将问题分解为以下子问题:
- 给定一个编码字符串 s,以 s[0] 开头的子字符串有多少种可能的解码方法?
- 给定一个编码字符串 s,以 s[1] 开头的子字符串有多少种可能的解码方法?
- ......
- 给定一个编码字符串 s,以 s[s.length() - 1] 开头的子字符串有多少种可能的解码方法?
通过依次解决这些子问题,我们可以得到整个字符串 s 的所有可能的解码方法。
实现步骤
-
初始化:
创建长度为 s.length() + 1 的数组 dp,其中 dp[i] 表示以 s[i] 开头的子字符串有多少种可能的解码方法。将 dp[s.length()] 初始化为 1,因为空字符串只有一种可能的解码方法。
-
迭代:
从 i = s.length() - 1 开始,依次递减至 i = 0。对于每个 i,计算以 s[i] 开头的子字符串有多少种可能的解码方法。具体步骤如下:
- 如果 s[i] 是一个有效的数字(即 1-9),那么 dp[i] = dp[i+1],因为以 s[i] 开头的子字符串只有唯一的一种解码方法,即以 s[i] 对应的字母开头。
- 如果 s[i] 和 s[i+1] 构成了一个有效的两位数(即 10-26),那么 dp[i] = dp[i+1] + dp[i+2],因为以 s[i] 开头的子字符串有两种可能的解码方法:一种是将 s[i] 和 s[i+1] 解码为一个字母,另一种是将 s[i] 单独解码为一个字母,然后将 s[i+1] 单独解码为一个字母。
-
返回结果:
返回 dp[0],即以 s[0] 开头的子字符串有多少种可能的解码方法。
代码示例
public class Solution {
public int numDecodings(String s) {
int[] dp = new int[s.length() + 1];
dp[s.length()] = 1;
for (int i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) != '0') {
dp[i] = dp[i+1];
}
if (i + 1 < s.length() && (s.charAt(i) == '1' || (s.charAt(i) == '2' && s.charAt(i+1) <= '6'))) {
dp[i] += dp[i+2];
}
}
return dp[0];
}
}
结语
LeetCode 91:解码方法是计算机编程中一个经典的动态规划算法问题,它要求我们计算给定编码字符串有多少种可能的解码方法。通过使用动态规划的思想,我们可以将原问题分解为一系列子问题,然后依次解决这些子问题,最终得到原问题的解。本文深入解析了 LeetCode 91 的问题背景、算法原理和实现步骤,帮助读者掌握这道编程难题的求解方法。