刷题使我快乐,满脸开心.jpg

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/decode-ways
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目

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

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

解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,"11106" 可以映射为:

  • "AAJF" ,将消息分组为 (1 1 10 6)
  • "KJF" ,将消息分组为 (11 10 6)
    注意,消息不能分组为  (1 11 06) ,因为 "06" 不能映射为 "F" ,这是由于 "6""06" 在映射中并不等价。

给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数

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

思路

这道题目使用动态规划将会比较简单

  • 动态数组定义:假设 f(n)n 长度字符串的解法
  • 动态方程:f(n) = f(n-1) + f(n-2),当然这个等式还会有一些限制,下面说
  • 初始化数据:f(0) = 1

f(n) 往下拆解时候,因为能 解码 的一定是 1-26 的数字,所以会有两个限制条件:

  • f(n-1) 需要满足第一个数字不是 0,前导零无法 解码

此时需要 s[n-1] 不为 0

  • f(n-2) 除了不能出现前导零之外需要满足形成的数字在 1-26 范围内

此时需要 s[n-2] 不为 0s[n-2]*10 + s[n-1] 应该是 1-26 之间的数字

大体思路就是这样,上代码

代码

func numDecodings(s string) int {
    n := len(s)
    f := make([]int, n+1)
    f[0] = 1
    for i := 1; i <= n; i++ {
        // 不能出现前导零
        if s[i-1] != '0' {
            f[i] += f[i-1]
        }
        // 不能出现前导零 并且 形成的数字需要在 1-26 之内
        if i > 1 && s[i-2] != '0' && ((s[i-2]-'0')*10+(s[i-1]-'0') <= 26) {
            f[i] += f[i-2]
        }
    }
    return f[n]
}