一条包含字母 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"
不同。
除了 上面描述的数字字母映射方案,编码消息中可能包含 '*'
字符,可以表示从 '1'
到 '9'
的任一数字(不包括 '0'
)。例如,编码字符串 "1*"
可以表示 "11"
、"12"
、"13"
、"14"
、"15"
、"16"
、"17"
、"18"
或 "19"
中的任意一条消息。对 "1*"
进行解码,相当于解码该字符串可以表示的任何编码消息。
给你一个字符串 s
,由数字和 '*'
字符组成,返回 解码 该字符串的方法 数目 。
由于答案数目可能非常大,返回 109 + 7
的 模 。
示例 1:
输入:s = "*" 输出:9 解释:这一条编码消息可以表示 "1"、"2"、"3"、"4"、"5"、"6"、"7"、"8" 或 "9" 中的任意一条。 可以分别解码成字符串 "A"、"B"、"C"、"D"、"E"、"F"、"G"、"H" 和 "I" 。 因此,"*" 总共有 9 种解码方法。
示例 2:
输入:s = "1*" 输出:18 解释:这一条编码消息可以表示 "11"、"12"、"13"、"14"、"15"、"16"、"17"、"18" 或 "19" 中的任意一条。 每种消息都可以由 2 种方法解码(例如,"11" 可以解码成 "AA" 或 "K")。 因此,"1*" 共有 9 * 2 = 18 种解码方法。
示例 3:
输入:s = "2*" 输出:15 解释:这一条编码消息可以表示 "21"、"22"、"23"、"24"、"25"、"26"、"27"、"28" 或 "29" 中的任意一条。 "21"、"22"、"23"、"24"、"25" 和 "26" 由 2 种解码方法,但 "27"、"28" 和 "29" 仅有 1 种解码方法。 因此,"2*" 共有 (6 * 2) + (3 * 1) = 12 + 3 = 15 种解码方法。
提示:
1 <= s.length <= 105
s[i]
是0 - 9
中的一位数字或字符'*'
只是在 91. 解码方法 的基础上加了些关于 *
的条件判断
class Solution:
def numDecodings(self, s: str) -> int:
mod = int(1e9 + 7)
n = len(s)
# dp[i - 2], dp[i - 1], dp[i]
a, b, c = 0, 1, 0
for i in range(1, n + 1):
# 1 digit
if s[i - 1] == "*":
c = 9 * b % mod
elif s[i - 1] != "0":
c = b
else:
c = 0
# 2 digits
if i > 1:
if s[i - 2] == "*" and s[i - 1] == "*":
c = (c + 15 * a) % mod
elif s[i - 2] == "*":
if s[i - 1] > "6":
c = (c + a) % mod
else:
c = (c + 2 * a) % mod
elif s[i - 1] == "*":
if s[i - 2] == "1":
c = (c + 9 * a) % mod
elif s[i - 2] == "2":
c = (c + 6 * a) % mod
elif (
s[i - 2] != "0"
and (ord(s[i - 2]) - ord("0")) * 10 + ord(s[i - 1]) - ord("0") <= 26
):
c = (c + a) % mod
a, b = b, c
return c
class Solution {
private static final int MOD = 1000000007;
public int numDecodings(String s) {
int n = s.length();
char[] cs = s.toCharArray();
// dp[i - 2], dp[i - 1], dp[i]
long a = 0, b = 1, c = 0;
for (int i = 1; i <= n; i++) {
// 1 digit
if (cs[i - 1] == '*') {
c = 9 * b % MOD;
} else if (cs[i - 1] != '0') {
c = b;
} else {
c = 0;
}
// 2 digits
if (i > 1) {
if (cs[i - 2] == '*' && cs[i - 1] == '*') {
c = (c + 15 * a) % MOD;
} else if (cs[i - 2] == '*') {
if (cs[i - 1] > '6') {
c = (c + a) % MOD;
} else {
c = (c + 2 * a) % MOD;
}
} else if (cs[i - 1] == '*') {
if (cs[i - 2] == '1') {
c = (c + 9 * a) % MOD;
} else if (cs[i - 2] == '2') {
c = (c + 6 * a) % MOD;
}
} else if (cs[i - 2] != '0' && (cs[i - 2] - '0') * 10 + cs[i - 1] - '0' <= 26) {
c = (c + a) % MOD;
}
}
a = b;
b = c;
}
return (int) c;
}
}
const mod int = 1e9 + 7
func numDecodings(s string) int {
n := len(s)
// dp[i - 2], dp[i - 1], dp[i]
a, b, c := 0, 1, 0
for i := 1; i <= n; i++ {
// 1 digit
if s[i-1] == '*' {
c = 9 * b % mod
} else if s[i-1] != '0' {
c = b
} else {
c = 0
}
// 2 digits
if i > 1 {
if s[i-2] == '*' && s[i-1] == '*' {
c = (c + 15*a) % mod
} else if s[i-2] == '*' {
if s[i-1] > '6' {
c = (c + a) % mod
} else {
c = (c + 2*a) % mod
}
} else if s[i-1] == '*' {
if s[i-2] == '1' {
c = (c + 9*a) % mod
} else if s[i-2] == '2' {
c = (c + 6*a) % mod
}
} else if s[i-2] != '0' && (s[i-2]-'0')*10+s[i-1]-'0' <= 26 {
c = (c + a) % mod
}
}
a, b = b, c
}
return c
}