91. 解码方法

216 阅读2分钟

题目

image.png

思路: 动态规划

  • 和剑指46的区别在于,这个题1对应A,单个的0是无效的。
  • 转移方程:dp[i] = dp[i - 1] + dp[i - 2]或者dp[i] = dp[i - 1];

0BE3ECED60C76EAB137CFF2FEB45424F.png

代码

DP多一位,方便初始化

class Solution {
    public int numDecodings(String s) {
        // dp[i]: ways of decode s substring [0, i-1].
        // this way helps recude custom checks for first two char
        // if let dp[i]: ways of decode s substring [0, i], when starting with dp[2],
        // we need to consider the first 3 digits, which is more complex
        int[] dp = new int[s.length() + 1];

        dp[0] = 1; // e.g. first two is 15, try dp[2] can explain we set dp[0]=1

        if (s.charAt(0) == '0') {
            dp[1] = 0;
        } else {
            dp[1] = 1;
        }
        
        for (int i = 2; i < s.length() + 1; i++) {
            // if we can decode single digit at index i - 1
            if (s.charAt(i - 1) != '0') {
                dp[i] = dp[i - 1];
            }

            int num = Integer.valueOf(s.substring(i - 2, i));
            if (num <= 26 && num >= 10) {
                dp[i] += dp[i - 2];
            }
        }

        return dp[s.length()];
    }
}

o1空间优化

class Solution {
   public int numDecodings(String s) {
       // dp[i]: ways of decode s substring [0, i-1].
       // this way helps recude custom checks for first two char
       // if let dp[i]: ways of decode s substring [0, i], when starting with dp[2],
       // we need to consider the first 3 digits, which is more complex
       // int[] dp = new int[s.length() + 1];

       // dp[0] = 1; // e.g. first two is 15, try dp[2] can explain we set dp[0]=1
       int prev2 = 1;


       // if (s.charAt(0) == '0') {
       //     prev = 0;
       // } else {
       //     prev = 1;
       // }

       int prev = s.charAt(0) == '0'? 0 : 1;


       for (int i = 2; i < s.length() + 1; i++) {
           // if we can decode single digit at index i - 1
           int cur = 0;
           if (s.charAt(i - 1) != '0') {
               // dp[i] = dp[i - 1];
               cur = prev;
           }

           int num = Integer.valueOf(s.substring(i - 2, i));
           if (num <= 26 && num >= 10) {
               // dp[i] += dp[i - 2];
               cur += prev2;
           }

           prev2 = prev;
           prev = cur;
       }

       return prev;
   }
}

dp 长= s,初始化麻烦

class Solution {
    public int numDecodings(String s) {
        int[] dp = new int[s.length()];
        //特判,“05,0”这样的不行
        if (s.charAt(0) == '0') {
            return 0;
        }
        dp[0] = 1;
        //长度为1
        if (s.length() == 1) {
            return dp[0];
        }
        // 长度为2
        int tmp = Integer.parseInt(s.substring(0, 2));
        if (s.charAt(1) == '0') {
            if (s.charAt(0) == '1' || s.charAt(0) == '2') {//只允许10、20
                dp[1] = 1;
            } else {//30、40不行
                return 0;
            }
        } else if (tmp >= 11 && tmp <= 26) {//上面已经排除了10、20的情况
            dp[1] = 2;
        } else {
            dp[1] = 1;
        }

        for (int i = 2; i < s.length(); i++) {
            int tmp1 = Integer.parseInt(s.substring(i - 1, i + 1));//当前位和前一位组成的字符串
            if (s.charAt(i) == '0') {
                if (s.charAt(i - 1) == '1' || s.charAt(i - 1) == '2') {//只允许10、20
                    dp[i] = dp[i - 2];
                } else {//30、40不行
                    return 0;
                }
            } else if (tmp1 >= 11 && tmp1 <= 26) {
                dp[i] = dp[i - 1] + dp[i - 2];
            } else {
                dp[i] = dp[i - 1];
            }
        }
        return dp[s.length() - 1];
    }
}