LeetCode-Decode Ways II

来源:互联网 发布:二次元网络漫画图片 编辑:程序博客网 时间:2024/06/07 18:05

算法分析与设计,第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: 9Explanation: 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
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 农村围墙大门尺寸 幼儿园围墙设计图片 别墅围墙大门尺寸 别墅院子围墙图片 一所没有围墙的大学 小学校园围墙文化 围墙锌钢护栏 彩钢板围墙施工方案 围墙护栏批发 围墙一般多高 别墅围墙款式 幼儿园围墙手绘图片 农村围墙大门 学校围墙高度标准 农村别墅围墙大门图片 围墙防盗刺防爬刺 铁艺围墙价格 小区围墙护栏 装配式围墙厂家 别墅铁艺大门 高校新校区无围墙 政入万山围子里 炕围子装修图片 政入万山围子里下一句 围子蛋糕店 床围子 客家围屋 围屋 龙南围屋 赣南围屋 龙南客家围屋旅游 龙南客家围屋 赣南客家围屋 圆形屏 半屏 围岩等级划分 围岩 围岩压力 围巾织法 织围巾教程 围巾围法