「力扣」第 91 题:解码方法(中等)


「力扣」第 91 题:解码方法(中等)

1、画图;2、分类(用加法)、分步(用乘法)

要求:一条包含字母 A-Z 的消息通过以下方式进行了编码:

'A' -> 1
'B' -> 2
...
'Z' -> 26

给定一个只包含数字的非空字符串,请计算解码方法的总数。

示例 1

输入: "12"
输出: 2
解释: 它可以解码为 "AB"(1 2)或者 "L"(12)。

示例 2

输入: "226"
输出: 3
解释: 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。

思路:拿具体的例子分析,比如:$12321$。假设我们已经解决了 dp[0]dp[1] ,从 dp[2] 开始考虑,分析 num[2]

1、如果 num[2] 不等于 $0$,那么 dp[2] 的情况和 dp[1] 是一样的,完成编码,这是一种情况;

2、如果 num[2] 跟前面的 num[1] 合起来能够组成一个字母,那么 dp[2]dp[0] 是一样的,完成编码,这是一种情况。

两种情况都能完成编码,求总数,其实就是他们的和,这里其实是加法计数原理的应用。

提示:注意数组下标越界问题。

Java 代码:

public class Solution {

    public int numDecodings(String s) {
        int len = s.length();
        if (len == 0) {
            return 0;
        }
        int[] dp = new int[len];
        dp[0] = s.charAt(0) == '0' ? 0 : 1;
        for (int i = 1; i < len; i++) {
            int res = 0;
            char cur = s.charAt(i);
            if (cur != '0') {
                res += dp[i - 1];
            }
            int pre = Integer.parseInt(s.substring(i - 1, i + 1));
            if (pre <= 26 && pre >= 10) {
                if (i - 2 < 0) {
                    res++;
                } else {
                    res += dp[i - 2];
                }
            }
            dp[i] = res;
            // System.out.println(Arrays.toString(dp));
        }
        return dp[len - 1];
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        String s = "12";
        int numDecodings = solution.numDecodings(s);
        System.out.println(numDecodings);
    }
}

Python 代码:

class Solution:

    def numDecodings(self, s):
        l = len(s)
        if l == 0:
            return 0

        if l == 1:
            return 1 if s[0] != '0' else 0
        dp = [0 for _ in range(l)]
        dp[0] = 1 if s[0] != '0' else 0
        for i in range(1, l):
            if s[i] != '0':
                # 如果不是 '0' ,那么 s[i] 就可以编码,所以 cur 就至少是 dp[i-1]
                dp[i] += dp[i - 1]
            if 9 < int(s[i - 1:i + 1]) < 27:
                # 可以和前面的数字组成一个编码
                if i - 2 < 0:
                    # 12
                    dp[i] += 1
                else:
                    dp[i] += dp[i - 2]
        return dp[l - 1]

Python 代码:

class Solution:
    def numDecodings(self, s: str) -> int:

        l = len(s)
        if l == 0:
            return 0

        if l == 1:
            return 1 if s[0] != '0' else 0
        dp = [0 for _ in range(l)]
        dp[0] = 1 if s[0] != '0' else 0
        for i in range(1, l):
            if s[i] != '0':
                # 如果不是 '0' ,那么 s[i] 就可以编码,所以 cur 就至少是  dp[i-1]
                dp[i] += dp[i - 1]
            if 9 < int(s[i - 1:i + 1]) < 27:
                # 可以和前面的数字组成一个编码
                # 这个判断是在写出 dp[i] += dp[i - 2] 以后,看出数组下标会越界,而增加的讨论
                if i - 2 < 0:
                    # 12
                    dp[i] += 1
                else:
                    dp[i] += dp[i - 2]
        return dp[l - 1]

Python 代码:

class Solution:
    def numDecodings(self, s: str) -> int:
        l = len(s)
        if l == 0:
            return 0
        dp = [1] + [0] * l
        if s[0] == '0':
            dp[1] = 0
        else:
            dp[1] = 1
        for i in range(1, l):
            if s[i] != '0':
                dp[i + 1] += dp[i]
            if s[i - 1] != '0' and int(s[i - 1:i + 1]) < 27:
                dp[i + 1] += dp[i - 1]
        return dp[-1]

说明:上面这段代码 dp[0] = 1 是故意这么定义的,为了防止像上一版代码那样的讨论。


文章作者: liweiwei419
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 liweiwei419 !
评论
 上一篇
「力扣」第 95 题:不同的二叉搜索树 II 「力扣」第 95 题:不同的二叉搜索树 II
「力扣」第 95 题:不同的二叉搜索树 II 链接:https://leetcode-cn.com/problems/unique-binary-search-trees-ii 给定一个整数 n,生成所有由 1 … n 为节点所组成的二
下一篇 
「力扣」第 72 题:编辑距离(困难) 「力扣」第 72 题:编辑距离(困难)
「力扣」第 72 题:编辑距离(困难) 链接:https://leetcode-cn.com/problems/edit-distance 题解链接:https://leetcode-cn.com/problems/edit-distanc
  目录