Let 1 represent ‘A’, 2 represents ‘B’, etc. Given a digit sequence, count the number of possible decodings of the given digit sequence.
Examples:
Input: digits[] = "121"
Output: 3
// The possible decodings are "ABA", "AU", "LA"
Input: digits[] = "1234"
Output: 3
// The possible decodings are "ABCD", "LCD", "AWD"
An empty digit sequence is considered to have one decoding. It may be assumed that the input contains valid digits from 0 to 9 and there are no leading 0’s, no extra trailing 0’s, and no two or more consecutive 0’s.
This problem is recursive and can be broken into sub-problems. We start from the end of the given digit sequence. We initialize the total count of decodings as 0. We recur for two subproblems.
1) If the last digit is non-zero, recur for the remaining (n-1) digits and add the result to the total count.
2) If the last two digits form a valid character (or smaller than 27), recur for remaining (n-2) digits and add the result to the total count.
Following is the implementation of the above approach.
C++
#include <cstring>
#include <iostream>
using namespace std;
int countDecoding( char * digits, int n)
{
if (n == 0 || n == 1)
return 1;
if (digits[0] == '0' )
return 0;
int count = 0;
if (digits[n - 1] > '0' )
count = countDecoding(digits, n - 1);
if (digits[n - 2] == '1'
|| (digits[n - 2] == '2'
&& digits[n - 1] < '7' ))
count += countDecoding(digits, n - 2);
return count;
}
int countWays( char * digits, int n)
{
if (n == 0 || (n == 1 && digits[0] == '0' ))
return 0;
return countDecoding(digits, n);
}
int main()
{
char digits[] = "1234" ;
int n = strlen (digits);
cout << "Count is " << countWays(digits, n);
return 0;
}
|
Java
class GFG {
static int countDecoding( char [] digits, int n)
{
if (n == 0 || n == 1 )
return 1 ;
if (digits[ 0 ] == '0' )
return 0 ;
int count = 0 ;
if (digits[n - 1 ] > '0' )
count = countDecoding(digits, n - 1 );
if (digits[n - 2 ] == '1'
|| (digits[n - 2 ] == '2'
&& digits[n - 1 ] < '7' ))
count += countDecoding(digits, n - 2 );
return count;
}
static int countWays( char [] digits, int n)
{
if (n == 0 || (n == 1 && digits[ 0 ] == '0' ))
return 0 ;
return countDecoding(digits, n);
}
public static void main(String[] args)
{
char digits[] = { '1' , '2' , '3' , '4' };
int n = digits.length;
System.out.printf( "Count is %d" ,
countWays(digits, n));
}
}
|
Python3
def numDecodings(s: str ) - > int :
if len (s) = = 0 or ( len (s) = = 1 and s[ 0 ] = = '0' ):
return 0
return numDecodingsHelper(s, len (s))
def numDecodingsHelper(s: str , n: int ) - > int :
if n = = 0 or n = = 1 :
return 1
count = 0
if s[n - 1 ] > "0" :
count = numDecodingsHelper(s, n - 1 )
if (s[n - 2 ] = = '1'
or (s[n - 2 ] = = '2'
and s[n - 1 ] < '7' )):
count + = numDecodingsHelper(s, n - 2 )
return count
if __name__ = = "__main__" :
digits = "1234"
print ( "Count is " , numDecodings(digits))
|
C#
using System;
class GFG {
static int countDecoding( char [] digits, int n)
{
if (n == 0 || n == 1)
return 1;
int count = 0;
if (digits[n - 1] > '0' )
count = countDecoding(digits, n - 1);
if (digits[n - 2] == '1'
|| (digits[n - 2] == '2'
&& digits[n - 1] < '7' ))
count += countDecoding(digits, n - 2);
return count;
}
static int countWays( char [] digits, int n)
{
if (n == 0 || (n == 1 && digits[0] == '0' ))
return 0;
return countDecoding(digits, n);
}
public static void Main()
{
char [] digits = { '1' , '2' , '3' , '4' };
int n = digits.Length;
Console.Write( "Count is " );
Console.Write(countWays(digits, n));
}
}
|
PHP
<?php
function countDecoding(& $digits , $n )
{
if ( $n == 0 || $n == 1)
return 1;
$count = 0;
if ( $digits [ $n - 1] > '0' )
$count = countDecoding( $digits , $n - 1);
if ( $digits [ $n - 2] == '1' ||
( $digits [ $n - 2] == '2' &&
$digits [ $n - 1] < '7' ) )
$count += countDecoding( $digits , $n - 2);
return $count ;
}
function countWays(& $digits , $n ){
if ( $n ==0 || ( $n == 1 && $digits [0] == '0' ))
return 0;
return countDecoding( $digits , $n );
}
$digits = "1234" ;
$n = strlen ( $digits );
echo "Count is " . countWays( $digits , $n );
?>
|
Javascript
<script>
function countDecoding(digits, n)
{
if (n == 0 || n == 1)
{
return 1;
}
if (digits[0] == '0' )
{
return 0;
}
let count = 0;
if (digits[n - 1] > '0' )
{
count = countDecoding(digits, n - 1);
}
if (digits[n - 2] == '1'
|| (digits[n - 2] == '2'
&& digits[n - 1] < '7' ))
{
count += countDecoding(digits, n - 2);
}
return count;
}
function countWays(digits, n)
{
if (n == 0 || (n == 1 && digits[0] == '0' ))
{
return 0;
}
return countDecoding(digits, n);
}
digits=[ '1' , '2' , '3' , '4' ];
let n = digits.length;
document.write( "Count is " ,countWays(digits, n));
</script>
|
Output:
Count is 3
The time complexity of above the code is exponential. If we take a closer look at the above program, we can observe that the recursive solution is similar to Fibonacci Numbers. Therefore, we can optimize the above solution to work in O(n) time using Dynamic Programming.
Following is the implementation for the same.
C++
#include <iostream>
#include <cstring>
using namespace std;
int countDecodingDP( char *digits, int n)
{
int count[n+1];
count[0] = 1;
count[1] = 1;
if (digits[0]== '0' )
return 0;
for ( int i = 2; i <= n; i++)
{
count[i] = 0;
if (digits[i-1] > '0' )
count[i] = count[i-1];
if (digits[i-2] == '1' ||
(digits[i-2] == '2' && digits[i-1] < '7' ) )
count[i] += count[i-2];
}
return count[n];
}
int main()
{
char digits[] = "1234" ;
int n = strlen (digits);
cout << "Count is " << countDecodingDP(digits, n);
return 0;
}
|
Java
import java.io.*;
class GFG
{
static int countDecodingDP( char digits[],
int n)
{
int count[] = new int [n + 1 ];
count[ 0 ] = 1 ;
count[ 1 ] = 1 ;
if (digits[ 0 ]== '0' )
return 0 ;
for ( int i = 2 ; i <= n; i++)
{
count[i] = 0 ;
if (digits[i - 1 ] > '0' )
count[i] = count[i - 1 ];
if (digits[i - 2 ] == '1' ||
(digits[i - 2 ] == '2' &&
digits[i - 1 ] < '7' ))
count[i] += count[i - 2 ];
}
return count[n];
}
public static void main (String[] args)
{
char digits[] = { '1' , '2' , '3' , '4' };
int n = digits.length;
System.out.println( "Count is " +
countDecodingDP(digits, n));
}
}
|
Python3
def countDecodingDP(digits, n):
count = [ 0 ] * (n + 1 );
count[ 0 ] = 1 ;
count[ 1 ] = 1 ;
for i in range ( 2 , n + 1 ):
count[i] = 0 ;
if (digits[i - 1 ] > '0' ):
count[i] = count[i - 1 ];
if (digits[i - 2 ] = = '1' or
(digits[i - 2 ] = = '2' and
digits[i - 1 ] < '7' ) ):
count[i] + = count[i - 2 ];
return count[n];
digits = "1234" ;
n = len (digits);
print ( "Count is" ,
countDecodingDP(digits, n));
|
C#
using System;
class GFG
{
static int countDecodingDP( char [] digits,
int n)
{
int [] count = new int [n + 1];
count[0] = 1;
count[1] = 1;
for ( int i = 2; i <= n; i++)
{
count[i] = 0;
if (digits[i - 1] > '0' )
count[i] = count[i - 1];
if (digits[i - 2] == '1' ||
(digits[i - 2] == '2' &&
digits[i - 1] < '7' ))
count[i] += count[i - 2];
}
return count[n];
}
public static void Main()
{
char [] digits = { '1' , '2' , '3' , '4' };
int n = digits.Length;
Console.WriteLine( "Count is " +
countDecodingDP(digits, n));
}
}
|
PHP
<?php
function countDecodingDP( $digits , $n )
{
$count [ $n +1]= array ();
$count [0] = 1;
$count [1] = 1;
for ( $i = 2; $i <= $n ; $i ++)
{
$count [ $i ] = 0;
if ( $digits [ $i -1] > '0' )
$count [ $i ] = $count [ $i -1];
if ( $digits [ $i -2] == '1' || ( $digits [ $i -2] == '2' && $digits [ $i -1] < '7' ) )
$count [ $i ] += $count [ $i -2];
}
return $count [ $n ];
}
$digits = "1234" ;
$n = strlen ( $digits );
echo "Count is " , countDecodingDP( $digits , $n );
#This code is contributed by ajit.
?>
|
Javascript
<script>
function countDecodingDP(digits, n)
{
let count = new Array(n + 1);
count[0] = 1;
count[1] = 1;
if (digits[0] == '0' )
return 0;
for (let i = 2; i <= n; i++)
{
count[i] = 0;
if (digits[i - 1] > '0' )
count[i] = count[i - 1];
if (digits[i - 2] == '1' ||
(digits[i - 2] == '2' &&
digits[i - 1] < '7' ))
count[i] += count[i - 2];
}
return count[n];
}
let digits = [ '1' , '2' , '3' , '4' ];
let n = digits.length;
document.write( "Count is " +
countDecodingDP(digits, n));
</script>
|
Output:
Count is 3
Time Complexity of the above solution is O(n) and it requires O(n) auxiliary space. We can reduce auxiliary space to O(1) by using the space-optimized version discussed in the Fibonacci Number Post.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above
Method 3 : ( Top Down DP )
Approach :
The above problem can be solved using Top down DP in the following way . One of the basic intuition is that we need to find the total number of ways to decode the given string such that each and every number in the string must lie in between the range of [ 1 , 26 ] both inclusive and without any leading 0’s . Let us consider an example string .
str = “123”
If we observe carefully we can observe a pattern over here i.e., the number of ways a particular substring can be decoded depends on the number of ways the remaining string is going to be decoded . For example , we want the number of ways to decode the string with “1” as a prefix the result depends on the number of ways the remaining string, i.e., “23” can be decoded . The number of ways the string “23” can be decoded are “2” , “3” and “23” there are 2 ways in both of these cases we can just append “1” to get the number of ways the given string can be decoded with “1” as a prefix i.e., “1” , “2” , “3” and “1” , “23” . Now we have found the number of ways we can decode the given string with “1” as a prefix but “12” also lies in between the range of [ 1 , 26 ] both inclusive the number of ways to decode the given string with “12” as a prefix depends on the result on how the remaining string is decoded . Here the remaining string is “3” it can be decoded in only 1 way so we can just append “12” in front of the string “3” to get it i.e., “12” , “3” . So the total number of ways the given string can be decoded are 3 ways .
But we can see some of the overlapping of subproblems over here i.e., when we are computing the total number of ways to decode the string “23” we are computing the number of ways the string “3” can be decoded as well as when we are computing the number of ways the string “12” can be decoded we are again computing the number of ways the string “3” can be decoded . So we can avoid this by storing the result of every substring . Here we can identify each and every sub problem through the index of the string . So , if at any point of time if we have already computed the number of ways the substring can be decoded we can directly return the result and that leads to a lot of optimization .
Below is the C++ implementation
C++
#include<bits/stdc++.h>
using namespace std;
int mod = 1e9 + 7;
int decodeMessage(vector< int > &dp, int s,string &str, int n)
{
if (s >= n)
return 1;
if (dp[s] != -1)
return dp[s];
int num,tc;
num = tc = 0;
for ( int i=s;i<n;i++)
{
num = num*10 + (str[i] - '0' );
if (num >= 1 and num <= 26)
{
int c = decodeMessage(dp,i+1,str,n);
tc = (tc%mod + c%mod)%mod;
}
else
break ;
}
return (dp[s] = tc);
}
int CountWays(string str)
{
int n = str.size();
if (n == 0)
return 1;
vector< int > dp(n,-1);
return decodeMessage(dp,0,str,n);
}
int main()
{
string str = "1234" ;
cout << CountWays(str) << endl;
return 0;
}
|
Java
import java.io.*;
class GFG {
static int mod = 1000000007 ;
static int decodeMessage( int [] dp, int s, String str, int n)
{
if (s >= n)
return 1 ;
if (dp[s] != - 1 )
return dp[s];
int num,tc;
num = tc = 0 ;
for ( int i=s;i<n;i++)
{
num = num* 10 + (( int )str.charAt(i) - '0' );
if (num >= 1 && num <= 26 )
{
int c = decodeMessage(dp, i + 1 , str, n);
tc = (tc%mod + c%mod)%mod;
}
else
break ;
}
return (dp[s] = tc);
}
static int CountWays(String str)
{
int n = str.length();
if (n == 0 )
return 1 ;
int [] dp = new int [n];
for ( int i = 0 ; i < n; i++){
dp[i] = - 1 ;
}
return decodeMessage(dp, 0 ,str,n);
}
public static void main(String args[])
{
String str = "1234" ;
System.out.println(CountWays(str));
}
}
|
Python3
mod = 1e9 + 7
def decodeMessage(dp, s, str , n):
if (s > = n):
return 1
if (dp[s] ! = - 1 ):
return dp[s]
num = 0
tc = 0
for i in range (s,n):
num = num * 10 + ( ord ( str [i]) - ord ( '0' ))
if (num > = 1 and num < = 26 ):
c = decodeMessage(dp, i + 1 , str , n)
tc = int ((tc % mod + c % mod) % mod)
else :
break
dp[s] = tc
return dp[s]
def CountWays( str ):
n = len ( str )
if (n = = 0 ):
return 1
dp = [ - 1 ] * (n)
return decodeMessage(dp, 0 , str , n)
if __name__ = = "__main__" :
str = "1234"
print (CountWays( str ))
|
C#
using System;
class GFG
{
static int mod = 1000000007;
static int decodeMessage( int [] dp, int s, string str, int n)
{
if (s >= n)
return 1;
if (dp[s] != -1)
return dp[s];
int num,tc;
num = tc = 0;
for ( int i=s;i<n;i++)
{
num = num*10 + (( int )str[i] - '0' );
if (num >= 1 && num <= 26)
{
int c = decodeMessage(dp, i + 1, str, n);
tc = (tc%mod + c%mod)%mod;
}
else
break ;
}
return (dp[s] = tc);
}
static int CountWays( string str)
{
int n = str.Length;
if (n == 0)
return 1;
int [] dp = new int [n];
for ( int i = 0; i < n; i++){
dp[i] = -1;
}
return decodeMessage(dp,0,str,n);
}
public static void Main()
{
string str = "1234" ;
Console.Write(CountWays(str));
}
}
|
Javascript
<script>
const mod = 1e9 + 7;
function decodeMessage(dp,s,str,n)
{
if (s >= n)
return 1;
if (dp[s] != -1)
return dp[s];
let num,tc;
num = tc = 0;
for (let i=s;i<n;i++)
{
num = num*10 + (str.charCodeAt(i) - '0' .charCodeAt(0));
if (num >= 1 && num <= 26)
{
let c = decodeMessage(dp,i+1,str,n);
tc = (tc%mod + c%mod)%mod;
}
else
break ;
}
return (dp[s] = tc);
}
function CountWays(str)
{
let n = str.length;
if (n == 0)
return 1;
let dp = new Array(n).fill(-1);
return decodeMessage(dp,0,str,n);
}
let str = "1234" ;
document.write(CountWays(str), "</br>" );
</script>
|
Output :
3
Time Complexity : O ( N ) where N is the length of the string . As we are solving each and every sub – problem only once .
Space Complexity : O ( N ) as we are using vector to store the result of each and every substring .