力扣:91.解码方法

155 阅读2分钟

「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

描述

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

'A' -> 1 'B' -> 2 ... 'Z' -> 26 要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,"11106" 可以映射为:

"AAJF" ,将消息分组为 (1 1 10 6) "KJF" ,将消息分组为 (11 10 6) 注意,消息不能分组为 (1 11 06) ,因为 "06" 不能映射为 "F" ,这是由于 "6" 和 "06" 在映射中并不等价。

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

题目数据保证答案肯定是一个 32 位 的整数。

  • 示例 1:
输入:s = "12"
输出:2
解释:它可以解码为 "AB"1 2)或者 "L"12)。
  • 示例 2:
输入:s = "226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
  • 示例3
输入:s = "0"
输出:0
解释:没有字符映射到以 0 开头的数字。
含有 0 的有效映射是 'J' -> "10"'T'-> "20" 。
由于没有字符,因此没有有效的方法对此进行解码,因为所有数字都需要映射。
  • 示例4
输入:s = "06"
输出:0
解释:"06" 不能映射到 "F" ,因为字符串含有前导 0"6""06" 在映射中并不等价)。
  • 提示:
  • 1 <= s.length <= 100
  • s 只包含数字,并且可能包含前导零。

解析

  1. 先扫描一遍把 00 和 30,40还有开头为0的直接过滤
  2. 根据0分成n个数组
  3. 判断一下每个字符串原本的末尾是否为0,是的话就截取掉最后一个(因为上面已经把不符合的过滤掉了所以这边肯定是可以的就要配合上前面一个当成一个数字)
  4. 然后就是欢乐的dp查找没有0的环节了。 判断一下是否大于26和数组越界问题就可以了

示例

class Solution {
    public static int numDecodings(String s) {
        char[] ch = s.toCharArray();
        int pre = 0;
        int i = 0;
        for (; i < ch.length; i++){
            int now = ch[i] - '0';
            int temp = pre * 10 + now;
            if (temp == 0 || (now == 0 && pre > 2)){
                return 0;
            }
            pre = now;
        }
​
        String[] noZero = s.split("0");
        int count = 1;
        String temp = "";
        //只有一个
        if (noZero.length == 1){
            temp = noZero[0];
            if (s.charAt(s.length()-1) == '0'){
                temp = temp.substring(0, temp.length()-1);
            }
            return numDecodingsNoZero(temp);
        }
        for (i = 0; i < noZero.length - 1; i++){
            temp = noZero[i];
            temp = temp.substring(0, temp.length()-1);
            count*= numDecodingsNoZero(temp);
        }
​
        temp = noZero[noZero.length-1];
        if (s.charAt(s.length()-1) == '0'){
            temp = temp.substring(0, temp.length()-1);
        }
        count*= numDecodingsNoZero(temp);
        return count;
    }
​
    public static int numDecodingsNoZero(String s){
        if (s.length() == 0){
            return 1;
        }
        char[] ch = s.toCharArray();
        int[] dp = new int[s.length() + 1];
        dp[0]=1;
        dp[1]=1;
        for (int i=2; i<dp.length; i++){
            //27,28,29    30以上都是只能单独当个数字
            if (ch[i-2] == '2' && ch[i-1] > '6' || ch[i-2] > '2'){
                dp[i] = dp[i-1];
            } else {
                //i-2存在才加
                dp[i] = dp[i-1] + dp[i-2];
            }
        }
        return dp[dp.length-1];
    }
}
​

运行结果:

执行结果:通过

执行用时:1 ms, 在所有 Java 提交中击败了59.61%的用户

内存消耗:36.7 MB, 在所有 Java 提交中击败了28.30%的用户

\