📌  相关文章
📜  计算给定数字序列的可能解码次数|套装2

📅  最后修改于: 2021-04-30 02:15:36             🧑  作者: Mango

给定一个由数字和*组成的编码字符串str ,该字符串可以由1-9的任意数字填充,任务是找到将该字符串解码为字母AZ的方式的数量。

注意:输入字符串包含0-9之间的数字和字符“ *”。
例子:

天真的方法:一个简单的解决方案是考虑所有可能的字符串解码,使用递归来解决问题。下面是该问题的递归树:

12*3
              /             \
           12*(3)           12(*3) 
         /     \            /      \
    12(*)(3)  1(2*)(3)  1(2)(*3)   ""
      /    \      \       /
1(2)(*)(3) ""     ""     ""   
    /
   ""

高效的方法:该想法是通过使用动态子程序来解决问题,该程序使用最佳子结构来考虑字符串的当前数字和前一位数字的所有情况以及它们对字符串进行解码的方式。

DP状态的定义:在此问题中dp[i]表示将字符串解码到i^{th}指数。

初始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]中的任何其他数字,则可能的解码方式等于对字符串进行解码的方式直至(i-1)^{th}指数。
      if (current != "*")
           dp[i] += dp[i-1]
      
  • 将当前字符包含为两位数以进行解码:如果要将当前字符解码为两位数,则有两种可能的情况:
    • 情况1:如果前一个字符等于"1"或者"2" ,那么可能还有两个可能取决于当前字符:
      • 情况1.1:如果当前字符等于"*" ,然后总的可能的方式来解码是9如果先前字符是1,否则如果6前一个字符是2。
      • 情况1.2:如果当前字符小于等于6,则对字符串进行解码的可能方式的总数将仅取决于对前一个字符进行解码的方式的数量。那是dp[i-2]
    • 情况2:如果前一个字符是"*" ,那么可能还有两个可能取决于当前字符:
      • 情况2.1:如果当前字符也是"*" ,那么案件总数将为15 * dp[i-2] ,因为必须已经包含前一个字符的解码方式的个位数。
      • 情况2.2:如果当前字符小于6,则总数为2*dp[i-2] ,因为那么选择第一个字符的数字的方式是2。即[1,2]。
      • 情况2.3:如果当前字符是任何数字,则方法总数将是仅解码前一位数字的方法数量。那是dp[i-2]

下面是上述方法的实现:

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


输出:
28

性能分析:

  • 时间复杂度: O(N)
  • 辅助空间: O(N)