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] = 0a = 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] <= 26b = 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 9. 回文数

C++&Python描述 LeetCode 704. 二分查找

C++&Python描述 LeetCode 162.寻找峰值

C++&Python 描述 LeetCode 8. 字符串转换整数 (atoi)

C++&Python 描述 LeetCode 2.两数相加