Loading

LeetCode91——解码方法

题目描述


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

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

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

题目数据保证答案肯定是一个 32 位的整数。

示例

输入:s = "12"
输出:2
解释:它可以解码为 "AB"(1 2)或者 "L"(12)。

题目分析


唉,其实就是一个上楼梯的有限制版,处理好边界,简单动归就完事了,好菜啊
对于字符串 \(s\) 来说,设 \(dp[i]\) 表示前 \(i\) 个字符种有 \(dp[i]\) 种组合方式可以用来解码。
对于 \(s[i]\) 来说:

  • s[i] = '0',则此时,只有当 s[i-1]='1's[i-1]='2',才能保证可以正确解码,因为 0 不能被单独解码,此时dp[i] = dp[i-2](因为 0 和前一位组合,所以方案数不发生变化);否则直接return 0,因为0不能被单独用来解码。
  • s[i] != '0'
    • s[i-1] = '1',则此时,\(s[i]\) 既可以自行单独用来解码,此时方案数为 \(dp[i-1]\) ;也可以与 \(s[i-1]\) 组合进行解码,此时方案数为 \(dp[i-2]\)。两种选择的方案数相加即为此种情况的总方案数,即dp[i] = dp[i-1] + dp[i-2]
    • s[i-1] = '2',则此时,只有当 s[i] >= 1 && s[i] <= 6时,\(s[i]\) 才既可以自行单独进行解码,也可以与 \(s[i-1]\) 组合进行解码,解释同上,此时,dp[i] = dp[i-1] + dp[i-2]
  • 若不符合以上所述情况,此时 \(s[i]\) 只能自行单独解码,此时 dp[i] = dp[i-1]

代码


接下来上代码,由于 \(s[0]\) 表示第一个字符,故转移方程需要稍作调整。
同时,我们让dp[0] = 1,没什么实际意义,但是为了理解方便,可以类比上楼梯,理解为前0个字母的解码方式一共有一种方案(好像不是那么恰当哈,不过差不多那个意思

class Solution {
    public int numDecodings(String s) {
        if(s.length() == 0 || s.charAt(0) == '0'){
            return 0;
        }
        int n = s.length();
        char[] arr = s.toCharArray();
        int[] dp = new int[n + 1];
        dp[0] = 1;
        dp[1] = 1;
        for(int i = 1; i < n;i ++){
            //转移方程调整解释:i=1时,表示第2个字符,所以我们把dp[i] 改成dp[i+1],以此类推对转移方程进行微调
            if(arr[i] == '0'){
                if(arr[i - 1] == '1' || arr[i - 1] == '2'){
                    dp[i + 1] = dp[i - 1];
                }else{
                    return 0;
                }
            }else if(arr[i - 1] == '1' || (arr[i - 1] == '2' && arr[i] <= '6')){
                dp[i + 1] = dp[i] + dp[i - 1];
            }else{
                dp[i + 1] = dp[i];
            }
        }
        return dp[n];
    }
}
posted @ 2020-11-24 13:20  Icdd  阅读(127)  评论(0)    收藏  举报