返回

探索 LeetCode #91:解码方法的多种可能

IOS

引言

LeetCode 中的 #91 题 "解码方法" 是一道经典的面试题,它考察了我们对于动态规划和字符串处理的理解。这道题要求我们求出一个字符串中可能的解码方式的数量,其中数字可以被翻译成相应的字母。

问题表述

给定一个仅包含数字 2-9 的字符串 s,请返回它有多少种不同的解码方式。

示例

  • 示例 1:
s = "12"
输出:2
解释:"12" 可以被解码为 "AB"1 -> A,2 -> B)或 "L"12 -> L)。
  • 示例 2:
s = "226"
输出:3
解释:"226" 可以被解码为 "BZ"2 -> B,2 -> Z),"VF"22 -> V,6 -> F)或 "BBF"22 -> BB,6 -> F)。

解决方案

为了解决这个问题,我们可以使用动态规划的方法。我们将建立一个大小为 s 长度 + 1 的数组 dp,其中 dp[i] 表示前 i 个字符的解码方式的数量。

我们从 dp[0] 开始,它显然等于 1,因为一个空字符串只有一种解码方式(空字符串)。然后,我们遍历 s 中的每个字符:

  • 如果当前字符是 0,则意味着前一个字符不能是 2 或 3,因为它们不能与 0 结合形成有效的解码。因此,dp[i] 等于 dp[i-1]。
  • 如果当前字符不是 0,则有两种情况:
    • 如果当前字符与前一个字符形成一个有效的两位数字(10-26),则 dp[i] 等于 dp[i-1] 加上 dp[i-2]。
    • 如果当前字符本身是一个有效的数字(1-9),则 dp[i] 等于 dp[i-1]。

通过这种方法,我们最终将得到 dp[s.length],它表示整个字符串的解码方式的数量。

代码实现

public int numDecodings(String s) {
    int[] dp = new int[s.length() + 1];
    dp[0] = 1;

    for (int i = 1; i <= s.length(); i++) {
        char c = s.charAt(i - 1);
        if (c != '0') {
            dp[i] = dp[i - 1];
            if (i > 1 && s.charAt(i - 2) != '0' && (s.charAt(i - 2) - '0') * 10 + (c - '0') <= 26) {
                dp[i] += dp[i - 2];
            }
        }
    }

    return dp[s.length()];
}

时间复杂度

动态规划算法的时间复杂度为 O(n),其中 n 是字符串 s 的长度。

空间复杂度

动态规划算法的空间复杂度为 O(n)。

结论

LeetCode #91 题 "解码方法" 是一个很好的练习动态规划和字符串处理技能的问题。通过使用动态规划的方法,我们可以高效地计算出字符串的解码方式的数量。希望这篇文章能帮助您理解这道题的解法。