解码方法

题目链接:

涉及知识:动态规划、分类讨论

分析:

首先从简单的情形进行分析,找出大概的状态转移方程,在逐步进行分类讨论。

假设给一个数串,". . . . . . 1258654326014 . . . . . .",dp[k] 表示 k 位数字的解码方法的总数,由于数字 1 - 26 分别表示字母 A - Z,数字为个位数或者两位数。则有两种情况:

  • 第 k 位一位数字表示一个字母:方案数为dp[k - 1],
  • 第(k - 1)和第 k 位两位数字表示一个字母:方案数为dp[k - 2]

因此,状态转移方程的一般形式为:dp[k] = dp[k - 1] + dp[k - 2]

但是,由于两种情况不一定可以同时取到,因此需要进行分类讨论。

  • 当第 k - 1 位不为 0 的时候:
    • 如果第 k 位不为 0,则第 k 位可以通过一位数字表示一个字母。
    • 当两位数字组合起来大于等于 10 小于等于 26 的时候,则可以通过两位数字的组合来表示一个字母。
  • 当第 k - 1 位为 0 的时候:
    • 如果第 k 位不为 0,则第 k 位可以通过一位数字表示一个字母。
  • 否则,存在连续两位同时为零,方案数为 0,直接返回 0

代码:

/*
 * @lc app=leetcode.cn id=91 lang=java
 *
 * [91] 解码方法
 */
class Solution {
    public int numDecodings(String s) {
        int[] dp = new int[s.length() + 5];
        dp[0] = 1; 
        dp[1] = 1;

        //特殊判断,首位为 0,无解
        if(s.length() == 0 || s.charAt(0) == '0'){
            return 0;
        }

        int i = 0;
        int tmp1 = 0;
        int tmp2 = 0;
        for(int j = 1; j < s.length(); ++j){
            i = j + 1;
            dp[i] = 0;

            //j - 1 位不为 0
            if(s.charAt(j - 1) != '0'){
                //j - 1 位为 0,j 位不为 0
                if(s.charAt(j) != '0'){
                    dp[i] += dp[i - 1];
                }

                tmp1 = s.charAt(j - 1) - '0';
                tmp2 = s.charAt(j) - '0';
                if((tmp1 == 1 || tmp1 == 2) && tmp1 * 10 + tmp2 <= 26 && tmp1 * 10 + tmp2 >= 10){
                    dp[i] += dp[i - 2];
                }
            } else if(s.charAt(j) != '0'){   //j - 1 位为 0,j 位不为 0
                dp[i] += dp[i - 1];
            } else {               //连续两个 0
                return 0;
            }
        }

        return dp[s.length()];
    }
}
原文地址:https://www.cnblogs.com/zcxhaha/p/11397365.html