题目描述

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

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

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

示例:

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

思路

1.这道题可以使用动态规划思想求解,而动态规划的套路都是一致的,先暴力递归求解,然后使用备忘录方法避免重复求解同一子问题,最后自底向上的找到状态转移方程求解。
2.当两位数小于27时状态转移方程为dp[i] = dp[i+1]dp[i+2];否则为dp[i] = dp[i+1]。

递归代码实现

   public int numDecodings(String s) {
        return numDecodings(s,0);
    }

    private int numDecodings(String s, int start){
        if(start == s.length()){
            return 1;
        }
        if(s.charAt(start) == '0'){
            return 0;
        }
        int ans1 = numDecodings(s,start+1);
        int ans2 = 0;
        if(start < s.length() - 1){
            int cur = Integer.parseInt(s.substring(start,start+2));
            if(cur <= 26){
                ans2 = numDecodings(s,start+2);
            }
        }
        return ans1 + ans2;
    }

备忘录代码实现

public int numDecodings(String s) {
        Map<Integer,Integer> map = new HashMap<>();
        return numDecodings(s,0,map);
    }

    private int numDecodings(String s, int start, Map<Integer,Integer> map){
        if(start == s.length()){
            return 1;
        }
        if(s.charAt(start) == '0'){
            return 0;
        }
        int res = map.getOrDefault(start,-1);
        if(res != -1)
            return res;
        int ans1 = numDecodings(s,start+1,map);
        int ans2 = 0;
        if(start < s.length() - 1){
            int cur = Integer.parseInt(s.substring(start,start+2));
            if(cur <= 26){
                ans2 = numDecodings(s,start+2,map);
            }
        }
        map.put(start,ans1 + ans2);
        return ans1 + ans2;
    }

动态规划代码实现

    public int numDecodings(String s) {
        int[] dp = new int[s.length()+1];
        dp[s.length()] = 1;
        if (s.charAt(s.length() - 1) != '0') {
            dp[s.length() - 1] = 1;
        }
        for (int i = s.length()-2; i >=0; i--) {
            if(s.charAt(i) == '0')
                continue;
            int cur = Integer.parseInt(s.substring(i,i+2));
            if(cur<=26)
                dp[i] = dp[i+1] + dp[i+2];
            else
                dp[i] = dp[i+1];
        }
        return dp[0];
    }