一条包含字母 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 只包含数字,并且可能包含前导零。
Related Topics
  • 字符串
  • 动态规划

  • 👍 953
  • 👎 0
    • 首位为0的定然不符合
    • 如果字符串长度只有1的话,肯定只有一种情况直接先返回
    • 如果字符串长度大于2,对第二位单独做个情况处理。
      • 如果第二个字符串为0,此时他不能单独处理,需要跟前一位合并解析
        1. 如果合并起来大于26,那么是解析不到对应的,直接返回0
        2. 如果合并起来不大于26,那么此时应该是10或者20的情况,只有一种解析方式,此时的组合数为1
      • 如果第二个字符串不为0
        1. 如果和前面组合起来小于等于26,说明可以分开也可以组合起来解析,此时组合数为1
        2. 如果大于26,则只能分开解析。可能组合数仍然为1
    • 从第三位往后开始解析处理,假设当前位置的索引为i
      • 和上面类似,如果当前字符为‘0’,只能和前面字符组合起来解析
        1. 如果值大于26,或者前一个数字也为0,无法解析,返回0
        2. 否则当前位置一定为10或者20,当前位置【i】和前一位【i-1】是一个整体,这样能解析出来的组合数量和【i-2】位能获得的组合数量是一致的
      • 如果当前位置字符不为0,
        • 如果和前面组合起来的话大于26,说明不能和前面的值组合起来解析,则当前位置能获得的组合数量和前面一位【i-1】一致
        • 如果不大于26
          • 如果前一位为0,即组合起来的值小于等于9,则不能和前一位组合,可能的组合数依旧和前一位【i-1】的组合数一致
          • 如果不为0,那么可能组合成11到19和21到26之间的数值,即说明可以和前一位组合(值等于【i-2】位的),也可以不组合(值等于【i-1】位的)。即为【i-1】加上【i-2】位的和
    class Solution {
        public int numDecodings(String s) {
            if (s.length() == 0 || s.charAt(0) == '0' ){
                return 0;
            }
            if (s.length() == 1){
                return 1;
            }
            int[] dp = new int[s.length()];
            dp[0] = 1;
            int i = 1;
            int curNum = s.charAt(i)-'0';
            int withBefore = (s.charAt(i-1)-'0') * 10 + (s.charAt(i)-'0');
            if (curNum==0 ){
                if (withBefore > 26 || withBefore ==0){
                    return 0;
                }
                dp[i] = 1;
            }else{
                if (withBefore <= 26){
                    dp[i] = 2;
                }else{
                    dp[i] = 1;
                }
            }
            i++;
            for (; i < dp.length; i++) {
                curNum = s.charAt(i)-'0';
                withBefore = (s.charAt(i-1)-'0') * 10 + (s.charAt(i)-'0');
                if (curNum == 0){
                    if (withBefore > 26 || withBefore ==0){
                        return 0;
                    }
                    dp[i] = dp[i-2];
                }else{
                    if (withBefore > 26){
                        dp[i] = dp[i-1];
                    }else {
                        if (withBefore>9){
                            dp[i] = dp[i-1] + dp[i-2];
                        }else {
                            dp[i] = dp[i-1];
                        }
                    }
                }
            }
            return dp[dp.length-1];
        }
    }

    这题动归本身并不复杂,复杂的各种逻辑情况的判定分析,分支略有点多。