LeetCode-Decode Ways II

算法分析与设计,第16周博客

639Decode Ways II

A message containing letters from A-Z is being encoded to numbers using the following mapping way:

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

Beyond that, now the encoded string can also contain the character '*', which can be treated as one of the numbers from 1 to 9.

Given the encoded message containing digits and the character '*', return the total number of ways to decode it.

Also, since the answer may be very large, you should return the output mod 109 + 7.

Example 1:

Input: "*"
Output: 9
Explanation: The encoded message can be decoded to the string: "A", "B", "C", "D", "E", "F", "G", "H", "I".

Example 2:

Input: "1*"
Output: 9 + 9 = 18

Note:

  1. The length of the input string will fit in range [1, 105].
  2. The input string will only contain the character '*' and digits '0' - '9'.

题意是,给定一个字母到数字的映射,然后给出一个包含数字和星号的字符串,要求这个字符串可以被解释为多少种不同的包含字母的字符串。

暂时先不考虑带有星号的情况。也就是只考虑带有数字的字符串,对于以s[i]结尾的子串,设它可以被解释为dp[i]种解释。那么有:dp[i] = a*dp[i-2] + b*dp[i-1];也就是说,当前的子串和它前两个子串是有关联的:

  1. 当前字符和前一个字符能被解释能字母时,那么将这两个字符和在一起形成一个整体,在与之前的字符连在一起,就有dp[i-2]种相关的解释方法。
  2. 当前字符和前一个字符不能被解释成字母是,那么这两个字母便不能合在一起,这时就相当于在之前的字符上多加了一个字符,那么有dp[i-1]种相关的方法。
所以,对于每一个字符,都只需要找出与之相关的系数a和b,就可以确定dp[i]。
那么,接下来考虑带有星号的情况。
首先来确定比较简单的系数b的情况,因为b是不能与之前的字符组成合法解释,所以只需要考虑这个字符本身即可:
  1. s[i] == '*' ,那么就可以代表1-9,这九种情况,所以 b = 9;
  2. s[i] == '0', 因为映射是从1开始的,所以单独一个0是非法的,所以 b=0;
  3. '1' <= s[i] <= '9',这些情况下都是合法的,所以 b = 1;
接下来讨论系数a的情况,这种情况下,当前字符与之前的字符组合形成代码,所以需要考虑两个字符。按照星号的分布,有以下几种情况:
  1. s[i-1] == '*' && s[i] == '*',两个都是星号。数字可以从11-19、21-26,所以 a = 9+6 = 15;
  2. s[i-1] == '*',前一个字符为星号,后一个字符不是。在这种情况下,在组成合法数字,那么s[i-1]必定为1或者2,那么就取决于s[i]的情况了。s[i] < '7',此时s[i-1]取1和2都行,所以 a = 2;s[i] >= '7',此时s[i-1]只能取1,所以 a = 1;
  3. s[i] == '*',前一个字符不是星号,当前字符是。这种情况下,取决于前一个字符。s[i-1] == '1',这种情况下s[i]可以取1-9的任意值,所以 a = 9; s[i-1] == '2',这种情况下,s[i]取1-6之间的任意值,所以 a = 6;其他情况都不能组成合法值,所以 a = 0。
  4. 两个字符都不是星号,那么要组成合法值必须要在10-26之间,此时 a = 1,其他情况 a = 0 。
解决完这两个系数的问题后,整个问题就基本得到了解决,不过仍需要注意的是,因为结果可能比较大,会超出int的数值范围,所以可能需要用到long的数值类型,总体的代码如下:
class Solution {
public:
    int ways(char c) {
        if (c == '*')
            return 9;
        if (c == '0')
            return 0;
        return 1;
    }
    int ways(char i, char j) {
        if (i == '*' && j == '*')
            return 15;
        if (i == '*')
            return (j <= '6' ? 2 : 1);
        if (j == '*') {
            if (i == '1')
                return 9;
            if (i == '2')
                return 6;
            return 0;
        }
        if (i == '1' || (i == '2' && j <= '6'))
            return 1;
        return 0;
    }
    int numDecodings(string s) {
        int n = s.length();
        if (n == 0 || s[0] == '0')
            return 0;
        long frt_2 = 1, frt_1 = ways(s[0]);
        long result = frt_1;
        long mod = 1000000007;
        for (int i = 1; i < n; ++i) {
            result = ways(s[i-1], s[i])*frt_2 + ways(s[i])*frt_1;
            result = result%mod;
            frt_2 = frt_1;
            frt_1 = result;
        }
        return result;
    }
};
最后来看下这个算法的时间和空间复杂度,整个代码中没有申请O(n) 数量级的变量,所以空间复杂是O(1)。而其中只用到了一个循环,而循环中每个步骤都是O(1)的时间复杂度,所以总体的时间复杂度是O(n)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值