刷题使我快乐,满脸开心.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]
不为0
且s[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]
}