给定一个由数字和*组成的编码字符串str ,它可以由任何数字1 – 9填充,任务是找到将该字符串解码为字母序列AZ 的方法数。
注意:输入字符串包含 0-9 的数字和字符“*”。
例子:
Input: str = “1*”
Output: 18
Explanation:
Since * can be replaced by any value from (1-9),
The given string can be decoded as A[A-I] + [J-R] = 9 + 9 ways
Input: str = “12*3”
Output: 28
朴素的方法:一个简单的解决方案是使用递归解决问题,考虑字符串的所有可能解码。
下面是问题的递归树:
12*3
/ \
12*(3) 12(*3)
/ \ / \
12(*)(3) 1(2*)(3) 1(2)(*3) ""
/ \ \ /
1(2)(*)(3) "" "" ""
/
""
有效的方法:这个想法是使用动态规划解决问题,使用最优子结构来考虑字符串的当前和前一个数字的所有情况以及它们解码字符串的方法数量。
DP 状态的定义:在这个问题中表示将字符串解码到指数。
初始 DP 状态:初始 DP 状态的值定义如下:
// Number of ways to decode
// an empty string
dp[0] = 1
// Number of ways to decode the
// first character
if (s[0] == '*')
dp[1] = 9 // 9 ways
else
dp[1] = 1
最优子结构:解码字符串当前字符一般有两种方式:
- 包括当前字符作为一位数进行解码:如果当前字符作为一位数使用,那么该字符通常有两种情况:
- 情况 1:如果当前字符等于 , 那么有 9 种可能的方法可以从 [1-9] 中取出任何数字并将其解码为 [AZ] 中的任何字符。
if (current == "*")
dp[i] += 9 * dp[i-1]
- 情况 2:如果当前字符等于 [0-9] 中的任何其他数字,则可能的解码方式数等于将字符串解码的方式数指数。
if (current != "*")
dp[i] += dp[i-1]
- 包括当前字符作为两位数进行解码:如果当前字符将被解码为两位数,那么有两种可能的情况:
- 情况 1:如果前一个字符等于要么 ,那么可能还有两种可能的子情况,这取决于当前字符:
- Case 1.1:如果当前字符等于 ,那么如果前一个字符是 1,那么总共可能的解码方式是 9,否则如果前一个字符是 2,那么总共可能的解码方式是 6。
- Case 1.2:如果当前字符小于等于 6,则字符串的可能解码方式总数将仅取决于解码到前一个字符的方式数量。那是
- 情况 2:如果前一个字符是 ,那么可能还有两种可能的子情况,这取决于当前字符:
- Case 2.1:如果当前字符也是 , 那么总病例数将是 ,因为必须已经包含了前一个字符的解码方式的个位数。
- Case 2.2:如果当前字符小于6,则总路数为 ,因为那么选择第一个字符的位数的方法数是2,即[1, 2]。
- Case 2.3:如果当前字符是任何数字,那么总的路数将是解码到前一个数字的路数。那是 .
- 情况 1:如果前一个字符等于要么 ,那么可能还有两种可能的子情况,这取决于当前字符:
C++
// C++ implementation to count the
// possible decodings of the given
// digit sequence
#include
using namespace std;
// Function to count the number of
// ways to decode the given digit
// sequence
int waysToDecode2(string s) {
int n = s.size();
// Array to store the dp states
vector dp(n+1,0);
// Case of empty string
dp[0]=1;
// Condition to check if the
// first character of string is 0
if(s[0]=='0')
return 0;
// Base case for single length
// string
dp[1]= ((s[0]=='*')? 9 : 1);
// Bottom-up dp for the string
for(int i=2;i<=n;i++)
{
// Previous character
char first= s[i-2];
// Current character
char second= s[i-1];
// Case to include the Current
// digit as a single digit for
// decoding the string
if(second=='*')
{
dp[i]+= 9*dp[i-1];
}
else if(second>'0')
dp[i]+=dp[i-1];
// Case to include the current
// character as two-digit for
// decoding the string
if(first=='1'|| first=='2')
{
// Condition to check if the
// current character is "*"
if(second=='*')
{
if(first=='1')
dp[i]+= 9 * dp[i-2];
else if(first=='2')
dp[i]+= 6 * dp[i-2];
}
// Condition to check if the
// current character is less than
// or equal to 26
else if(((first-'0')* 10 +
(second-'0'))<= 26)
dp[i]+=dp[i-2];
}
// Condition to check if the
// Previous digit is equal to "*"
else if(first=='*')
{
if(second=='*')
{
dp[i]+= 15 * dp[i-2];
}
else if(second<='6')
dp[i]+= 2* dp[i-2];
else
dp [i]+= dp[i-2];
}
}
return dp[n];
}
// Driver Code
int main() {
string str = "12*3";
// Function Call
cout << waysToDecode2(str) << endl;
return 0;
}
Java
// Java implementation to count the
// possible decodings of the given
// digit sequence
class GFG{
// Function to count the number of
// ways to decode the given digit
// sequence
static int waysToDecode2(char []s)
{
int n = s.length;
// Array to store the dp states
int []dp = new int[n + 1];
// Case of empty String
dp[0] = 1;
// Condition to check if the
// first character of String is 0
if(s[0] == '0')
return 0;
// Base case for single length
// String
dp[1] = ((s[0] == '*') ? 9 : 1);
// Bottom-up dp for the String
for(int i = 2; i <= n; i++)
{
// Previous character
char first = s[i - 2];
// Current character
char second = s[i - 1];
// Case to include the Current
// digit as a single digit for
// decoding the String
if(second == '*')
{
dp[i] += 9 * dp[i - 1];
}
else if(second > '0')
dp[i] += dp[i - 1];
// Case to include the current
// character as two-digit for
// decoding the String
if(first == '1' || first == '2')
{
// Condition to check if the
// current character is "*"
if(second == '*')
{
if(first == '1')
dp[i] += 9 * dp[i - 2];
else if(first == '2')
dp[i] += 6 * dp[i - 2];
}
// Condition to check if the
// current character is less than
// or equal to 26
else if(((first - '0') * 10 +
(second - '0')) <= 26)
{
dp[i] += dp[i - 2];
}
}
// Condition to check if the
// previous digit is equal to "*"
else if(first == '*')
{
if(second == '*')
{
dp[i] += 15 * dp[i - 2];
}
else if(second <= '6')
{
dp[i] += 2 * dp[i - 2];
}
else
{
dp[i] += dp[i - 2];
}
}
}
return dp[n];
}
// Driver Code
public static void main(String[] args)
{
String str = "12*3";
// Function Call
System.out.print(waysToDecode2(
str.toCharArray()) + "\n");
}
}
// This code is contributed by amal kumar choubey
C#
// C# implementation to count the
// possible decodings of the given
// digit sequence
using System;
class GFG{
// Function to count the number of
// ways to decode the given digit
// sequence
static int waysToDecode2(char []s)
{
int n = s.Length;
// Array to store the dp states
int []dp = new int[n + 1];
// Case of empty String
dp[0] = 1;
// Condition to check if the
// first character of String is 0
if(s[0] == '0')
return 0;
// Base case for single length
// String
dp[1] = ((s[0] == '*') ? 9 : 1);
// Bottom-up dp for the String
for(int i = 2; i <= n; i++)
{
// Previous character
char first = s[i - 2];
// Current character
char second = s[i - 1];
// Case to include the current
// digit as a single digit for
// decoding the String
if(second == '*')
{
dp[i] += 9 * dp[i - 1];
}
else if(second > '0')
{
dp[i] += dp[i - 1];
}
// Case to include the current
// character as two-digit for
// decoding the String
if(first == '1' || first == '2')
{
// Condition to check if the
// current character is "*"
if(second == '*')
{
if(first == '1')
{
dp[i] += 9 * dp[i - 2];
}
else if(first == '2')
{
dp[i] += 6 * dp[i - 2];
}
}
// Condition to check if the
// current character is less than
// or equal to 26
else if(((first - '0') * 10 +
(second - '0')) <= 26)
{
dp[i] += dp[i - 2];
}
}
// Condition to check if the
// previous digit is equal to "*"
else if(first == '*')
{
if(second == '*')
{
dp[i] += 15 * dp[i - 2];
}
else if(second <= '6')
{
dp[i] += 2 * dp[i - 2];
}
else
{
dp[i] += dp[i - 2];
}
}
}
return dp[n];
}
// Driver Code
public static void Main(String[] args)
{
String str = "12*3";
// Function Call
Console.Write(waysToDecode2(
str.ToCharArray()) + "\n");
}
}
// This code is contributed by amal kumar choubey
Javascript
输出:
28
- 时间复杂度: O(N)
- 辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。