[leetCode]91. 解码方法

题目

链接:https://leetcode-cn.com/problems/decode-ways

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

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

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

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

示例 1:

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

示例 2:

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

示例 3:

输入:s = "0"
输出:0

示例 4:

输入:s = "1"
输出:1

示例 5:

输入:s = "2"
输出:1
 

提示:

1 <= s.length <= 100
s 只包含数字,并且可能包含前导零。

动态规化

分析第一种情况子串中不包含0
假设 s = 226
s子串2长度为1解码方式为1种:2
s子串22长度为2解码方式为2种2,2 、 22
s子串226长度为2解码方式为3种2,2,6、22,6、2,26

dp[i]代表长度为i的字符串有几种解码方式,dp[1] = 1

每当再字符串子串后面增加一个字符,比如在22后面增加6,6单独看新子串的解码方式有2种:2,2,6、22,6,如果新增字符6与前一个字符相结合在[10,26]范围内则解码方式又增加一种:2,26。所以状态转移方程为:
d p [ i ] + = d p [ i − 1 ] dp[i] += dp[i-1] dp[i]+=dp[i1]
如果 新增字符与最后一个字符组合后符合条件
d p [ i ] + = d p [ i − 2 ] dp[i] += dp[i-2] dp[i]+=dp[i2]

  以上不含0的情况,如果字符串s最后一位为0比如说1020这种情况,那么0只能和前一位组合起来看所以状态转移方程为

d p [ i ] + = d p [ i − 2 ] dp[i] += dp[i-2] dp[i]+=dp[i2]
所以dp[0]要初始化为1。
综上状态转移方程为:

s最后一个字母不为0则:
d p [ i ] + = d p [ i − 1 ] dp[i] += dp[i-1] dp[i]+=dp[i1]
如果 新增字符与最后一个字符组合后符合条件
d p [ i ] + = d p [ i − 2 ] dp[i] += dp[i-2] dp[i]+=dp[i2]

代码如下:

class Solution {

    public int numDecodings(String s) {
        // 如果首字母为'0'则不和任何字母对应,之间返回0
        if (s == null || s.length() == 0 || s.charAt(0) == '0') return 0;

        int n = s.length();
        // 状态设置: dp[i] 表示长度为i的字符串的解码方式的次数
        int[] dp = new int[n + 1];
        dp[0] = 1; // 考虑10这种情况dp[2] += dp[2-2]
        dp[1] = 1;// 长度为1的字符串解码方式为一种也就是s[0]
        for (int i = 2; i <= n; i++) {
            if (s.charAt(i-1) != '0') {// 如果字符串s最后一个字符不为0,那么可以单独拿出来 比如 11--> 1,1
                dp[i] += dp[i-1]; 
            }
            int num = Integer.valueOf(s.substring(i-2,i));
            if (num >= 10 && num <= 26) {
                dp[i] += dp[i-2];
            }
        }
        System.out.println(Arrays.toString(dp));
        return dp[n];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值