加码方法

237 阅读3分钟

题目

一条包含字母 A-Z 的消息通过以下映射进行了 编码 :

'A' -> 1 'B' -> 2 ... 'Z' -> 26 要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,"111" 可以将 "1" 中的每个 "1" 映射为 "A" ,从而得到 "AAA" ,或者可以将 "11" 和 "1"(分别为 "K" 和 "A" )映射为 "KA" 。注意,"06" 不能映射为 "F" ,因为 "6" 和 "06" 不同。

给你一个只含数字的 非空 字符串 num ,请计算并返回 解码 方法的 总数 。

题目数据保证答案肯定是一个 32 位 的整数。 输入:s = "226" 输出:3 解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。 示例 3:

输入:s = "0" 输出:0 解释:没有字符映射到以 0 开头的数字。含有 0 的有效映射是 'J' -> "10" 和 'T'-> "20" 。由于没有字符,因此没有有效的方法对此进行解码,因为所有数字都需要映射。

动态规划

public class Main {


    public static void main(String[] args) {

        Main main = new Main();
        main.numDecodings("2611055971756562");

    }

    public int numDecodings(String s) {
        if (s.startsWith("0")) {
            return 0;
        }
        char [] codeCharArray = s.toCharArray();
        int [] dpTable = new int[s.length()];
        dpTable[0] = 1;
        int pre_data = Integer.valueOf(String.valueOf(codeCharArray[0]));
        for (int i = 1; i < codeCharArray.length; i ++) {
            int data = Integer.valueOf(String.valueOf(codeCharArray[i]));
            if (data == 0) {
                if (pre_data <= 2 && pre_data != 0) {
                    // 能结合
                    dpTable[i] = i - 2 >= 0 ? dpTable[i - 2] : dpTable[i - 1];
                } else {
                    return 0;
                }
            } else {
                if (pre_data == 0) {
                    // 不能结合
                    dpTable[i] = dpTable[i - 1];
                } else {
                    if (pre_data > 2 || (pre_data == 2 && data >=7 )) {
                        // 不能结合
                        dpTable[i] = dpTable[i - 1];
                    } else {
                        // 能结合
                        dpTable[i] = i - 2 >= 0 ? dpTable[i - 1] + dpTable[i - 2] : dpTable[i - 1] + 1;
                    }
                }
            }
            pre_data = data;
        }
        return dpTable[s.length() - 1];

    }


}

基本思路

  1. 题目可以得到最优子结构, 每次添加一个数字对于整体的解码可能的影响, 只和当前数字和前一个数字有关.

因此可以得到4中情况, 前一个数字为0, 当前数字为0或者不为0, 前一个数字不为0时, 当前数字为0或者不为0, 这四种情况中, 还需要细分出当前数字能否和前一个数字结合的问题, 即是否在(1-26之间).

  1. 能结合 就说明将后两位看成一个整体, 那么可能的数目就是和dp[i - 2]一直, 假设i - 2的时候可能数组为[2, 2], [22], 那如果新增一个26, 那么不就是[2, 2, 26], [22, 26]

  2. 不能结合的时候 新加的一位数目等于dp[i - 1], 假设假设i - 1的时候可能数组为[2, 2], [22], 新增一个0, 那么可能的数组就是[2, 2, 0], [22, 0]

  3. 利用dp table记录数字从1位到2位, 3位.....的可能的解码数量

  4. 状态转移方程与情况相关, 需要根据每一种情况, 思考列出