C++&Python描述 LeetCode 639. 解码方法 II
Posted 亓官劼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++&Python描述 LeetCode 639. 解码方法 II相关的知识,希望对你有一定的参考价值。
C++&Python描述 LeetCode 639. 解码方法 II
大家好,我是亓官劼(qí guān jié ),在公众号、CSDN、GitHub、B站、华为开发者论坛等平台分享一些技术博文,全平台的id皆为:亓官劼(qí guān jié ),
除以上平台,其他的亓官劼id都不是本人,有不少网站在冒充,注意甄别
。
放弃不难,但坚持一定很酷!时光荏苒,未来可期,一起加油~建了个小交流群,Q群:545611263,要进微信群的话可以加我V:
qiguanjie2015
备注拉群即可。近期对博文更新策略做了些调整,微信公众号后期将用来更新一些总结性的文章(更新频率将会很低),类似于刷题、一些bug解决等杂项记录的blog就更新在CSDN、华为开发者论坛和GitHub上。同时文章在GitHub中进行了开源,内含本系列文章目前已刷的各个题解和解题思路,GitHub地址为:LeetCode,如果文章对你有帮助的话可以来GitHub点个star,如果有更好的解题思路的话,也可以来GitHub提交~一起改进
题目
一条包含字母 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
中的一位数字或字符'*'
解题思路
DP。使用f[i]
表示前i
个字符的解码种类,由于对于1-26
对应不同的解码,所以分为一个字符的解码和两个字符的解码两种情况。设当前s[i]
一个字符的时候有a
种情况,s[i-1],s[i]
两个字符的时候有b
种情况,那么f[i] = a * f[i-1] + b * f[i-2]
对于单个字符s[i]
时:
s[i] = *
:a = 9
s[i] = 0
:a = 0
s[i] = [1-9]中的一个
:a = 1
对于两个字符s[i-1], s[i]
时:
s[i-1] = *, s[i] = *
:b = 15
s[i-1] = 1, s[i] = *
:b = 9
s[i-1] = 2, s[i] = *
:b = 6
s[i-1] = 0, s[i] = *
:b = 0
s[i-1] = *, s[i] = [0-6]
:b = 2
s[i-1] = *, s[i] = [7-9]
:b = 1
s[i-1] = [1-2], s[i] = [1-9], 并且s[i-1]s[i] <= 26
:b = 1
- other:
b = 0
C++实现
class Solution {
public:
int compute_a(char ch){
if(ch == '*') return 9;
if(ch == '0') return 0;
return 1;
}
int compute_b(char ch_1, char ch_2){
if(ch_1 == '*' && ch_2 == '*') return 15;
if(ch_1 == '0' && ch_2 == '*') return 0;
if(ch_1 == '1' && ch_2 == '*') return 9;
if(ch_1 == '2' && ch_2 == '*') return 6;
if(ch_1 == '*' && ch_2 <= '6' && ch_2 >= '0') return 2;
if(ch_1 == '*' && ch_2 <= '9' && ch_2 >= '7') return 1;
if(ch_1 >= '1' && ch_1 <= '2' && ch_2 >= '0' && ch_2 <= '9' && (int(ch_1-'0')*10 + int(ch_2-'0')) <= 26 ) return 1;
return 0;
}
int numDecodings(string s) {
int len = s.length(), mod = 1e9+7, a_f = 0, b_f = 0;
vector<int> f(len+5);
f[0] = 1;
for(int i = 1; i <= len; i++){
a_f = ((long long)compute_a(s[i-1]) * f[i-1]) % mod;
f[i] = a_f;
if(i >= 2){
b_f = ((long long) compute_b(s[i-2], s[i-1]) * f[i-2]) % mod;
f[i] =((long long) (b_f + f[i])) % mod;
}
}
return f[len];
}
};
Python实现
class Solution:
def compute_a(ch):
if ch == '*': return 9;
if ch == '0': return 0;
return 1;
def compute_b(ch_1, ch_2):
if ch_1 == '*' and ch_2 == '*' : return 15;
if ch_1 == '0' and ch_2 == '*' : return 0;
if ch_1 == '1' and ch_2 == '*' : return 9;
if ch_1 == '2' and ch_2 == '*' : return 6;
if ch_1 == '*' and ch_2 <= '6' and ch_2 >= '0': return 2;
if ch_1 == '*' and ch_2 <= '9' and ch_2 >= '7': return 1;
if ch_1 >= '1' and ch_1 <= '2' and ch_2 >= '0' and ch_2 <= '9' and int(ch_1+ch_2) <= 26: return 1
return 0;
def numDecodings(self, s: str) -> int:
length = s.__len__()
mod = int(1e9+7)
f = [0 for _ in range(length+5)]
f[0] = 1
for i in range(1,length+1):
f[i] = (Solution.compute_a(s[i-1]) * f[i-1] + Solution.compute_b(s[i-2],s[i-1]) * f[i-2]) % mod if i >= 2 else (Solution.compute_a(s[i-1]) * f[i-1]) % mod
return f[length]
以上是关于C++&Python描述 LeetCode 639. 解码方法 II的主要内容,如果未能解决你的问题,请参考以下文章
C++&Python 描述 LeetCode 7. 整数反转
C++&Python描述 LeetCode 704. 二分查找
C++&Python描述 LeetCode 162.寻找峰值