Leetcode91.解码方法

题目描述
一条包含字母 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) 。

思路
1.用递归很容易做,f(n) = f(n-1)+f(n-2)
但是这道题要注意的是对0的处理
如果输入字符串“30”,返回的值是0,边界条件实在难搞
最后用递归做没有AC,235 / 258 个通过测试用例,最后是时间超过限制

class Solution {
    int count = 0;
    boolean invalid = false;
    public int numDecodings(String s) {
        //表面上在考几种解码方法,其实在考能有几种划分方式
       //用递归来求
       if(s.charAt(0) == '0')
          return 0;
       helper(s);
       return invalid? 0 : count; 
    }
    public void helper(String s){
        if(s.length() <= 1){
            if(s.equals("0")){
                invalid = true;
            }
            count++;
            return;
        }
        int val = Integer.valueOf(s.substring(0,2));
        if(val == 10 || val == 20){
           if(s.length() == 2 || s.charAt(2) != '0') 
                helper(s.substring(2,s.length()));
            else
                invalid = true;
        }else if(val <= 26){
            helper(s.substring(1,s.length()));
            if(s.length() == 2 || s.charAt(2) != '0')
                helper(s.substring(2,s.length()));
        }else{
            if(s.charAt(1) == '0')
                invalid = true;
            helper(s.substring(1,s.length()));
        }
        
    }
}

2.看别人的答案才想起来可以用动态规划来做
因此,这道题的正解是用动态规划来做

class Solution {
    public int numDecodings(String s) {
        int[] dp = new int[s.length()+1];
        dp[s.length()] = 1;
        for(int i = s.length() - 1;i >= 0;i--){
            char c = s.charAt(i);
            if(c == '0'){
                if(i > 0){
                    if(s.charAt(i-1) == '1' || s.charAt(i-1) == '2'){
                        dp[i] = 0;
                        continue;
                    }else{
                        dp[0] = 0;
                        break;
                    }
                }else{
                    dp[0] = 0;
                    break;
                }
            }
            if(i < s.length() - 1 && Integer.valueOf(s.substring(i,i+2)) <= 26){
                dp[i] = dp[i+1]+dp[i+2];
            }else{
                dp[i] = dp[i+1];
            }
        }
        return dp[0]; 
    }
}

还可以继续优化,可以不使用数组来存储,压缩空间,不过我没有自己写写看了,可以看下自己在Leetcode收藏的帖子
3.思路1的递归是采用的自上而下来解决问题,会产生重复问题
例如:12258
1和2258 12和258
2258又可以分解为 258又可以分解为
2和258 22和58 2和58 25和8
258又出现了

如果 从数字的末尾开始,从右往左计算,就可以消除重复的子问题

java->递归->动态规划->空间压缩

你可能感兴趣的:(算法与数据结构)