给定一个包含数字和字符“*”(即隐藏字符)的字符串S ,任务是找到对给定字符串的这个隐藏字符进行解码的方法数。
由于答案可能非常大,将其取模10 9 +7 返回。
A string containing letters from A-Z can be encoded into numbers using the following mapping:
‘A’ -> “1”
‘B’ -> “2”
‘C’ -> “3”
‘D’ -> “4”
…
…
‘Z’ -> “26”
Note: Characters including 0 are not included in the problem like (J → 10).
例子:
Input: s = “*”
Output: 9
Explanation: The encoded message can represent any of the encoded messages “1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, or “9”.
Each of these can be decoded to the strings “A”, “B”, “C”, “D”, “E”, “F”, “G”, “H”, and “I” respectively.
Hence, there are a total of 9 ways to decode “*”.
Input: s = “1*”
Output: 18
Explanation: The encoded message can represent any of the encoded messages “11”, “12”, “13”, “14”, “15”, “16”, “17”, “18”, or “19”.
Each of these encoded messages have 2 ways to be decoded (e.g. “11” can be decoded to “AA” or “K”).
Hence, there are a total of 9 × 2 = 18 ways to decode “1*”.
方法:
这个问题可以通过观察到任何恒定数目可以在字符被任一解码这是一个单位的数字,或者它可以被解码成一个双位的数字,如果第(i-1)个字符为“1”或来解决(第i-1)个字符是‘2’ ,第i个字符在1到6之间。因此,当前状态依赖于前一个状态,可以使用动态规划来解决这个问题。请按照以下步骤解决问题:
1. 让dp[i]表示解码从0到i的字符串字符的方法数。
2. 如果第i 个字符是‘*’ :
- dp[i] = dp[i-1]*9考虑到‘*’可以是1 到 9 ,单独作为一个字符来考虑。
- 现在,如果i和i-1字符组合在一起,那么,
- 如果第(i-1) 个字符是‘*’,那么两个“**”一起可以形成15 个可能的字符(如 13 将形成字符’M’),因此我们将15×dp[i-2] 添加到dp[我] 。
- 如果第(i-1) 个字符是‘1’则dp[i] = dp[i] + 9×dp[i-2]因为可以解码的可能字符是11 到 19 (K 到 S)。
- 如果第(i-1) 个字符是‘2’则dp[i] = dp[i] + 6×dp[i-2]因为它可以取21 到 26 之间的值。
3.如果第i个字符不是‘*’:
- dp[i] = dp[i] + dp[i-1]将第 i 个字符单独视为一个数字。
- 现在,如果可以将第(i-1) 个字符和第 i 个字符组合在一起,则将dp[i-2] 添加到 dp[i]。
下面是上述方法的实现:
C++
#include
using namespace std;
int M = 1000000007;
int waysOfDecoding(string s)
{
vector dp((int)s.size()+1);
dp[0] = 1;
// check the first character of the string
// if it is '*' then 9 ways
dp[1] = s[0] == '*'
? 9
: s[0] == '0' ? 0 : 1;
// traverse the string
for (int i = 1; i < (int)s.size(); i++) {
// If s[i] == '*' there can be
// 9 possible values of *
if (s[i] == '*') {
dp[i + 1] = 9 * dp[i];
// If previous character is 1
// then words that can be formed
// are K(11), L(12), M(13), N(14)
// O(15), P(16), Q(17), R(18), S(19)
if (s[i - 1] == '1')
dp[i + 1]
= (dp[i + 1] + 9 * dp[i - 1]) % M;
// If previous character is 2
// then the words that can be formed
// are U(21), V(22), W(23), X(24)Y(25), Z(26)
else if (s[i - 1] == '2')
dp[i + 1]
= (dp[i + 1] + 6 * dp[i - 1]) % M;
// If the previous digit is * then
// all 15 2- digit characters can be
// formed
else if (s[i - 1] == '*')
dp[i + 1]
= (dp[i + 1] + 15 * dp[i - 1]) % M;
}
else {
// taking the value from previous step
dp[i + 1] = s[i] != '0' ? dp[i] : 0;
// If previous character is 1 then
// the i-1th character and ith
// character can be decoded in
// a single character therefore,
// adding dp[i-1].
if (s[i - 1] == '1')
dp[i + 1]
= (dp[i + 1] + dp[i - 1])
% M;
// If previous character is 2
// and ith character is less than
// 6
// then the i-1th character and
// ith character can be decoded in
// a single character therefore,
// adding dp[i-1].
else if (s[i - 1] == '2'
&& s[i] <= '6')
dp[i + 1]
= (dp[i + 1] + dp[i - 1]) % M;
// If previous character is * then
// it will contain the above 2 cases
else if (s[i - 1] == '*')
dp[i + 1]
= (dp[i + 1]
+ (s[i] <= '6' ? 2 : 1)
* dp[i - 1])
% M;
}
}
return dp[(int)s.size()];
}
int main()
{
string s = "12";
cout<
Java
// Java program for the above approach
import java.io.*;
class GFG {
static int M = 1000000007;
static int waysOfDecoding(String s)
{
long[] dp = new long[s.length() + 1];
dp[0] = 1;
// check the first character of the string
// if it is '*' then 9 ways
dp[1] = s.charAt(0) == '*'
? 9
: s.charAt(0) == '0' ? 0 : 1;
// traverse the string
for (int i = 1; i < s.length(); i++) {
// If s[i] == '*' there can be
// 9 possible values of *
if (s.charAt(i) == '*') {
dp[i + 1] = 9 * dp[i];
// If previous character is 1
// then words that can be formed
// are K(11), L(12), M(13), N(14)
// O(15), P(16), Q(17), R(18), S(19)
if (s.charAt(i - 1) == '1')
dp[i + 1]
= (dp[i + 1] + 9 * dp[i - 1]) % M;
// If previous character is 2
// then the words that can be formed
// are U(21), V(22), W(23), X(24)Y(25), Z(26)
else if (s.charAt(i - 1) == '2')
dp[i + 1]
= (dp[i + 1] + 6 * dp[i - 1]) % M;
// If the previous digit is * then
// all 15 2- digit characters can be
// formed
else if (s.charAt(i - 1) == '*')
dp[i + 1]
= (dp[i + 1] + 15 * dp[i - 1]) % M;
}
else {
// taking the value from previous step
dp[i + 1] = s.charAt(i) != '0' ? dp[i] : 0;
// If previous character is 1 then
// the i-1th character and ith
// character can be decoded in
// a single character therefore,
// adding dp[i-1].
if (s.charAt(i - 1) == '1')
dp[i + 1]
= (dp[i + 1] + dp[i - 1])
% M;
// If previous character is 2
// and ith character is less than
// 6
// then the i-1th character and
// ith character can be decoded in
// a single character therefore,
// adding dp[i-1].
else if (s.charAt(i - 1) == '2'
&& s.charAt(i) <= '6')
dp[i + 1]
= (dp[i + 1] + dp[i - 1]) % M;
// If previous character is * then
// it will contain the above 2 cases
else if (s.charAt(i - 1) == '*')
dp[i + 1]
= (dp[i + 1]
+ (s.charAt(i) <= '6' ? 2 : 1)
* dp[i - 1])
% M;
}
}
return (int)dp[s.length()];
}
public static void main(String[] args)
{
String s = "12";
System.out.println(waysOfDecoding(s));
}
}
C#
// C# program for the above approach
using System;
class GFG{
static int M = 1000000007;
static int waysOfDecoding(String s)
{
long[] dp = new long[s.Length + 1];
dp[0] = 1;
// Check the first character of the string
// if it is '*' then 9 ways
dp[1] = s[0] == '*' ? 9 : s[0] == '0' ? 0 : 1;
// Traverse the string
for(int i = 1; i < s.Length; i++)
{
// If s[i] == '*' there can be
// 9 possible values of *
if (s[i] == '*')
{
dp[i + 1] = 9 * dp[i];
// If previous character is 1
// then words that can be formed
// are K(11), L(12), M(13), N(14)
// O(15), P(16), Q(17), R(18), S(19)
if (s[i - 1] == '1')
dp[i + 1] = (dp[i + 1] + 9 *
dp[i - 1]) % M;
// If previous character is 2
// then the words that can be formed
// are U(21), V(22), W(23), X(24)Y(25),
// Z(26)
else if (s[i - 1] == '2')
dp[i + 1] = (dp[i + 1] + 6 *
dp[i - 1]) % M;
// If the previous digit is * then
// all 15 2- digit characters can be
// formed
else if (s[i - 1] == '*')
dp[i + 1] = (dp[i + 1] + 15 *
dp[i - 1]) % M;
}
else
{
// Taking the value from previous step
dp[i + 1] = s[i] != '0' ? dp[i] : 0;
// If previous character is 1 then
// the i-1th character and ith
// character can be decoded in
// a single character therefore,
// adding dp[i-1].
if (s[i - 1] == '1')
dp[i + 1] = (dp[i + 1] + dp[i - 1]) % M;
// If previous character is 2
// and ith character is less than
// 6
// then the i-1th character and
// ith character can be decoded in
// a single character therefore,
// adding dp[i-1].
else if (s[i - 1] == '2' && s[i] <= '6')
dp[i + 1] = (dp[i + 1] + dp[i - 1]) % M;
// If previous character is * then
// it will contain the above 2 cases
else if (s[i - 1] == '*')
dp[i + 1] = (dp[i + 1] + (s[i] <= '6' ? 2 : 1) *
dp[i - 1]) % M;
}
}
return (int)dp[s.Length];
}
// Driver code
public static void Main()
{
String s = "12";
Console.WriteLine(waysOfDecoding(s));
}
}
// This code is contributed by rishavmahato348
Javascript
C++
// C++ program for the above approach
#include
using namespace std;
int M = 1000000007;
int waysOfDecoding(string s)
{
long first = 1,
second = s[0] == '*' ? 9 : s[0] == '0' ? 0 : 1;
for(int i = 1; i < s.size(); i++)
{
long temp = second;
// If s[i] == '*' there can be
// 9 possible values of *
if (s[i] == '*')
{
second = 9 * second;
// If previous character is 1
// then words that can be formed
// are K(11), L(12), M(13), N(14)
// O(15), P(16), Q(17), R(18), S(19)
if (s[i - 1] == '1')
second = (second + 9 * first) % M;
// If previous character is 2
// then the words that can be formed
// are U(21), V(22), W(23), X(24)Y(25), Z(26)
else if (s[i - 1] == '2')
second = (second + 6 * first) % M;
// If the previous digit is * then
// all 15 2- digit characters can be
// formed
else if (s[i - 1] == '*')
second = (second + 15 * first) % M;
}
// If s[i] != '*'
else
{
second = s[i] != '0' ? second : 0;
// Adding first in second
// if s[i-1]=1
if (s[i - 1] == '1')
second = (second + first) % M;
// Adding first in second if
// s[i-1] == 2 and s[i]<='6'
else if (s[i - 1] == '2' && s[i] <= '6')
second = (second + first) % M;
// If s[i-1] == '*' the union
// of above 2 cases has to be done
else if (s[i - 1] == '*')
second = (second + (s[i] <= '6' ? 2 : 1) *
first) % M;
}
first = temp;
}
return(int)second;
}
// Driver code
int main()
{
string s = "*";
cout << waysOfDecoding(s);
return 0;
}
// This code is contributed by rishavmahato348
Java
// Java program for the above approach
import java.io.*;
class GFG {
static int M = 1000000007;
static int waysOfDecoding(String s)
{
long first = 1, second
= s.charAt(0) == '*'
? 9
: s.charAt(0) == '0' ? 0 : 1;
for (int i = 1; i < s.length(); i++) {
long temp = second;
// If s[i] == '*' there can be
// 9 possible values of *
if (s.charAt(i) == '*') {
second = 9 * second;
// If previous character is 1
// then words that can be formed
// are K(11), L(12), M(13), N(14)
// O(15), P(16), Q(17), R(18), S(19)
if (s.charAt(i - 1) == '1')
second = (second + 9 * first) % M;
// If previous character is 2
// then the words that can be formed
// are U(21), V(22), W(23), X(24)Y(25), Z(26)
else if (s.charAt(i - 1) == '2')
second = (second + 6 * first) % M;
// If the previous digit is * then
// all 15 2- digit characters can be
// formed
else if (s.charAt(i - 1) == '*')
second = (second + 15 * first) % M;
}
// If s[i] != '*'
else {
second = s.charAt(i) != '0' ? second : 0;
// Adding first in second
// if s[i-1]=1
if (s.charAt(i - 1) == '1')
second = (second + first) % M;
// Adding first in second if
// s[i-1] == 2 and s[i]<='6'
else if (s.charAt(i - 1) == '2'
&& s.charAt(i) <= '6')
second = (second + first) % M;
// if s[i-1] == '*' the union
// of above 2 cases has to be done
else if (s.charAt(i - 1) == '*')
second = (second
+ (s.charAt(i) <= '6' ? 2 : 1)
* first)
% M;
}
first = temp;
}
return (int)second;
}
public static void main(String[] args)
{
String s = "*";
System.out.println(waysOfDecoding(s));
}
}
C#
// C# program for the above approach
using System;
class GFG{
static int M = 1000000007;
static int waysOfDecoding(string s)
{
long first = 1,
second = s[0] == '*' ? 9 : s[0] == '0' ? 0 : 1;
for(int i = 1; i < s.Length; i++)
{
long temp = second;
// If s[i] == '*' there can be
// 9 possible values of *
if (s[i] == '*')
{
second = 9 * second;
// If previous character is 1
// then words that can be formed
// are K(11), L(12), M(13), N(14)
// O(15), P(16), Q(17), R(18), S(19)
if (s[i - 1] == '1')
second = (second + 9 * first) % M;
// If previous character is 2
// then the words that can be formed
// are U(21), V(22), W(23), X(24)Y(25), Z(26)
else if (s[i - 1] == '2')
second = (second + 6 * first) % M;
// If the previous digit is * then
// all 15 2- digit characters can be
// formed
else if (s[i - 1] == '*')
second = (second + 15 * first) % M;
}
// If s[i] != '*'
else
{
second = s[i] != '0' ? second : 0;
// Adding first in second
// if s[i-1]=1
if (s[i - 1] == '1')
second = (second + first) % M;
// Adding first in second if
// s[i-1] == 2 and s[i]<='6'
else if (s[i - 1] == '2' && s[i] <= '6')
second = (second + first) % M;
// if s[i-1] == '*' the union
// of above 2 cases has to be done
else if (s[i - 1] == '*')
second = (second + (s[i] <= '6' ? 2 : 1) *
first) % M;
}
first = temp;
}
return (int)second;
}
// Driver code
static public void Main()
{
string s = "*";
Console.WriteLine(waysOfDecoding(s));
}
}
// This code is contributed by patel2127
Javascript
2
时间复杂度: O(n)
辅助空间: O(n)
进一步优化空间
如果仔细观察上面的代码,会发现dp[i]的值是使用dp[i-1]和dp[i-2] 找到的。所以为了进一步优化空间,我们可以使用三个变量,而不是创建一个长度为N的dp数组——第二个(存储dp[i]的值),第一个(存储dp[i-2] 的值),和temp (存储dp[i-1] 的值)。因此,在找到second(dp[i])的值后,修改first = temp和temp = second ,然后使用变量first和temp再次计算second(dp[i])的值。
C++
// C++ program for the above approach
#include
using namespace std;
int M = 1000000007;
int waysOfDecoding(string s)
{
long first = 1,
second = s[0] == '*' ? 9 : s[0] == '0' ? 0 : 1;
for(int i = 1; i < s.size(); i++)
{
long temp = second;
// If s[i] == '*' there can be
// 9 possible values of *
if (s[i] == '*')
{
second = 9 * second;
// If previous character is 1
// then words that can be formed
// are K(11), L(12), M(13), N(14)
// O(15), P(16), Q(17), R(18), S(19)
if (s[i - 1] == '1')
second = (second + 9 * first) % M;
// If previous character is 2
// then the words that can be formed
// are U(21), V(22), W(23), X(24)Y(25), Z(26)
else if (s[i - 1] == '2')
second = (second + 6 * first) % M;
// If the previous digit is * then
// all 15 2- digit characters can be
// formed
else if (s[i - 1] == '*')
second = (second + 15 * first) % M;
}
// If s[i] != '*'
else
{
second = s[i] != '0' ? second : 0;
// Adding first in second
// if s[i-1]=1
if (s[i - 1] == '1')
second = (second + first) % M;
// Adding first in second if
// s[i-1] == 2 and s[i]<='6'
else if (s[i - 1] == '2' && s[i] <= '6')
second = (second + first) % M;
// If s[i-1] == '*' the union
// of above 2 cases has to be done
else if (s[i - 1] == '*')
second = (second + (s[i] <= '6' ? 2 : 1) *
first) % M;
}
first = temp;
}
return(int)second;
}
// Driver code
int main()
{
string s = "*";
cout << waysOfDecoding(s);
return 0;
}
// This code is contributed by rishavmahato348
Java
// Java program for the above approach
import java.io.*;
class GFG {
static int M = 1000000007;
static int waysOfDecoding(String s)
{
long first = 1, second
= s.charAt(0) == '*'
? 9
: s.charAt(0) == '0' ? 0 : 1;
for (int i = 1; i < s.length(); i++) {
long temp = second;
// If s[i] == '*' there can be
// 9 possible values of *
if (s.charAt(i) == '*') {
second = 9 * second;
// If previous character is 1
// then words that can be formed
// are K(11), L(12), M(13), N(14)
// O(15), P(16), Q(17), R(18), S(19)
if (s.charAt(i - 1) == '1')
second = (second + 9 * first) % M;
// If previous character is 2
// then the words that can be formed
// are U(21), V(22), W(23), X(24)Y(25), Z(26)
else if (s.charAt(i - 1) == '2')
second = (second + 6 * first) % M;
// If the previous digit is * then
// all 15 2- digit characters can be
// formed
else if (s.charAt(i - 1) == '*')
second = (second + 15 * first) % M;
}
// If s[i] != '*'
else {
second = s.charAt(i) != '0' ? second : 0;
// Adding first in second
// if s[i-1]=1
if (s.charAt(i - 1) == '1')
second = (second + first) % M;
// Adding first in second if
// s[i-1] == 2 and s[i]<='6'
else if (s.charAt(i - 1) == '2'
&& s.charAt(i) <= '6')
second = (second + first) % M;
// if s[i-1] == '*' the union
// of above 2 cases has to be done
else if (s.charAt(i - 1) == '*')
second = (second
+ (s.charAt(i) <= '6' ? 2 : 1)
* first)
% M;
}
first = temp;
}
return (int)second;
}
public static void main(String[] args)
{
String s = "*";
System.out.println(waysOfDecoding(s));
}
}
C#
// C# program for the above approach
using System;
class GFG{
static int M = 1000000007;
static int waysOfDecoding(string s)
{
long first = 1,
second = s[0] == '*' ? 9 : s[0] == '0' ? 0 : 1;
for(int i = 1; i < s.Length; i++)
{
long temp = second;
// If s[i] == '*' there can be
// 9 possible values of *
if (s[i] == '*')
{
second = 9 * second;
// If previous character is 1
// then words that can be formed
// are K(11), L(12), M(13), N(14)
// O(15), P(16), Q(17), R(18), S(19)
if (s[i - 1] == '1')
second = (second + 9 * first) % M;
// If previous character is 2
// then the words that can be formed
// are U(21), V(22), W(23), X(24)Y(25), Z(26)
else if (s[i - 1] == '2')
second = (second + 6 * first) % M;
// If the previous digit is * then
// all 15 2- digit characters can be
// formed
else if (s[i - 1] == '*')
second = (second + 15 * first) % M;
}
// If s[i] != '*'
else
{
second = s[i] != '0' ? second : 0;
// Adding first in second
// if s[i-1]=1
if (s[i - 1] == '1')
second = (second + first) % M;
// Adding first in second if
// s[i-1] == 2 and s[i]<='6'
else if (s[i - 1] == '2' && s[i] <= '6')
second = (second + first) % M;
// if s[i-1] == '*' the union
// of above 2 cases has to be done
else if (s[i - 1] == '*')
second = (second + (s[i] <= '6' ? 2 : 1) *
first) % M;
}
first = temp;
}
return (int)second;
}
// Driver code
static public void Main()
{
string s = "*";
Console.WriteLine(waysOfDecoding(s));
}
}
// This code is contributed by patel2127
Javascript
9
时间复杂度: O(n)
辅助空间: O(1)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。