Given a length n, count the number of strings of length n that can be made using ‘a’, ‘b’ and ‘c’ with at-most one ‘b’ and two ‘c’s allowed.
Examples :
Input : n = 3
Output : 19
Below strings follow given constraints:
aaa aab aac aba abc aca acb acc baa
bac bca bcc caa cab cac cba cbc cca ccb
Input : n = 4
Output : 39
Asked in Google Interview
A simple solution is to recursively count all possible combination of string that can be mode up to latter ‘a’, ‘b’, and ‘c’.
Below is implementation of above idea
C++
#include<bits/stdc++.h>
using namespace std;
int countStr( int n, int bCount, int cCount)
{
if (bCount < 0 || cCount < 0) return 0;
if (n == 0) return 1;
if (bCount == 0 && cCount == 0) return 1;
int res = countStr(n-1, bCount, cCount);
res += countStr(n-1, bCount-1, cCount);
res += countStr(n-1, bCount, cCount-1);
return res;
}
int main()
{
int n = 3;
cout << countStr(n, 1, 2);
return 0;
}
|
Java
import java.io.*;
class GFG
{
static int countStr( int n,
int bCount,
int cCount)
{
if (bCount < 0 || cCount < 0 ) return 0 ;
if (n == 0 ) return 1 ;
if (bCount == 0 && cCount == 0 ) return 1 ;
int res = countStr(n - 1 , bCount, cCount);
res += countStr(n - 1 , bCount - 1 , cCount);
res += countStr(n - 1 , bCount, cCount - 1 );
return res;
}
public static void main (String[] args)
{
int n = 3 ;
System.out.println(countStr(n, 1 , 2 ));
}
}
|
Python 3
def countStr(n, bCount, cCount):
if (bCount < 0 or cCount < 0 ):
return 0
if (n = = 0 ) :
return 1
if (bCount = = 0 and cCount = = 0 ):
return 1
res = countStr(n - 1 , bCount, cCount)
res + = countStr(n - 1 , bCount - 1 , cCount)
res + = countStr(n - 1 , bCount, cCount - 1 )
return res
if __name__ = = "__main__" :
n = 3
print (countStr(n, 1 , 2 ))
|
C#
using System;
class GFG
{
static int countStr( int n,
int bCount,
int cCount)
{
if (bCount < 0 || cCount < 0)
return 0;
if (n == 0) return 1;
if (bCount == 0 && cCount == 0)
return 1;
int res = countStr(n - 1,
bCount, cCount);
res += countStr(n - 1,
bCount - 1, cCount);
res += countStr(n - 1,
bCount, cCount - 1);
return res;
}
static public void Main ()
{
int n = 3;
Console.WriteLine(countStr(n, 1, 2));
}
}
|
PHP
<?php
function countStr( $n , $bCount ,
$cCount )
{
if ( $bCount < 0 ||
$cCount < 0)
return 0;
if ( $n == 0)
return 1;
if ( $bCount == 0 &&
$cCount == 0)
return 1;
$res = countStr( $n - 1,
$bCount ,
$cCount );
$res += countStr( $n - 1,
$bCount - 1,
$cCount );
$res += countStr( $n - 1,
$bCount ,
$cCount - 1);
return $res ;
}
$n = 3;
echo countStr( $n , 1, 2);
?>
|
Javascript
<script>
function countStr(n, bCount, cCount)
{
if (bCount < 0 || cCount < 0) return 0;
if (n == 0) return 1;
if (bCount == 0 && cCount == 0) return 1;
let res = countStr(n - 1, bCount, cCount);
res += countStr(n - 1, bCount - 1, cCount);
res += countStr(n - 1, bCount, cCount - 1);
return res;
}
let n = 3;
document.write(countStr(n, 1, 2));
</script>
|
Output :
19
Time complexity of above solution is exponential.
Efficient Solution
If we drown a recursion tree of above code, we can notice that same values appear multiple times. So we store results which are used later if repeated.
C++
#include<bits/stdc++.h>
using namespace std;
int countStrUtil( int dp[][2][3], int n, int bCount=1,
int cCount=2)
{
if (bCount < 0 || cCount < 0) return 0;
if (n == 0) return 1;
if (bCount == 0 && cCount == 0) return 1;
if (dp[n][bCount][cCount] != -1)
return dp[n][bCount][cCount];
int res = countStrUtil(dp, n-1, bCount, cCount);
res += countStrUtil(dp, n-1, bCount-1, cCount);
res += countStrUtil(dp, n-1, bCount, cCount-1);
return (dp[n][bCount][cCount] = res);
}
int countStr( int n)
{
int dp[n+1][2][3];
memset (dp, -1, sizeof (dp));
return countStrUtil(dp, n);
}
int main()
{
int n = 3;
cout << countStr(n);
return 0;
}
|
Java
class GFG
{
static int countStrUtil( int [][][] dp, int n,
int bCount, int cCount)
{
if (bCount < 0 || cCount < 0 )
{
return 0 ;
}
if (n == 0 )
{
return 1 ;
}
if (bCount == 0 && cCount == 0 )
{
return 1 ;
}
if (dp[n][bCount][cCount] != - 1 )
{
return dp[n][bCount][cCount];
}
int res = countStrUtil(dp, n - 1 , bCount, cCount);
res += countStrUtil(dp, n - 1 , bCount - 1 , cCount);
res += countStrUtil(dp, n - 1 , bCount, cCount - 1 );
return (dp[n][bCount][cCount] = res);
}
static int countStr( int n, int bCount, int cCount)
{
int [][][] dp = new int [n + 1 ][ 2 ][ 3 ];
for ( int i = 0 ; i < n + 1 ; i++)
{
for ( int j = 0 ; j < 2 ; j++)
{
for ( int k = 0 ; k < 3 ; k++)
{
dp[i][j][k] = - 1 ;
}
}
}
return countStrUtil(dp, n,bCount,cCount);
}
public static void main(String[] args)
{
int n = 3 ;
int bCount = 1 , cCount = 2 ;
System.out.println(countStr(n,bCount,cCount));
}
}
|
Python3
def countStrUtil(dp, n, bCount = 1 ,cCount = 2 ):
if (bCount < 0 or cCount < 0 ):
return 0
if (n = = 0 ):
return 1
if (bCount = = 0 and cCount = = 0 ):
return 1
if (dp[n][bCount][cCount] ! = - 1 ):
return dp[n][bCount][cCount]
res = countStrUtil(dp, n - 1 , bCount, cCount)
res + = countStrUtil(dp, n - 1 , bCount - 1 , cCount)
res + = countStrUtil(dp, n - 1 , bCount, cCount - 1 )
dp[n][bCount][cCount] = res
return dp[n][bCount][cCount]
def countStr(n):
dp = [ [ [ - 1 for x in range (n + 2 )] for y in range ( 3 )] for z in range ( 4 )]
return countStrUtil(dp, n)
if __name__ = = "__main__" :
n = 3
print (countStr(n))
|
C#
using System;
class GFG
{
static int countStrUtil( int [,,] dp, int n,
int bCount=1, int cCount=2)
{
if (bCount < 0 || cCount < 0)
return 0;
if (n == 0)
return 1;
if (bCount == 0 && cCount == 0)
return 1;
if (dp[n,bCount,cCount] != -1)
return dp[n,bCount,cCount];
int res = countStrUtil(dp, n - 1, bCount, cCount);
res += countStrUtil(dp, n - 1, bCount - 1, cCount);
res += countStrUtil(dp, n - 1, bCount, cCount - 1);
return (dp[n, bCount, cCount] = res);
}
static int countStr( int n)
{
int [,,] dp = new int [n + 1, 2, 3];
for ( int i = 0; i < n + 1; i++)
for ( int j = 0; j < 2; j++)
for ( int k = 0; k < 3; k++)
dp[i, j, k] = -1;
return countStrUtil(dp, n);
}
static void Main()
{
int n = 3;
Console.Write(countStr(n));
}
}
|
Javascript
<script>
function countStrUtil(dp , n, bCount , cCount)
{
if (bCount < 0 || cCount < 0)
{
return 0;
}
if (n == 0)
{
return 1;
}
if (bCount == 0 && cCount == 0)
{
return 1;
}
if (dp[n][bCount][cCount] != -1)
{
return dp[n][bCount][cCount];
}
var res = countStrUtil(dp, n - 1, bCount, cCount);
res += countStrUtil(dp, n - 1, bCount - 1, cCount);
res += countStrUtil(dp, n - 1, bCount, cCount - 1);
return (dp[n][bCount][cCount] = res);
}
function countStr(n , bCount , cCount)
{
dp = Array(n+1).fill(0).map
(x => Array(2).fill(0).map
(x => Array(3).fill(0)));
for (i = 0; i < n + 1; i++)
{
for (j = 0; j < 2; j++)
{
for (k = 0; k < 3; k++)
{
dp[i][j][k] = -1;
}
}
}
return countStrUtil(dp, n,bCount,cCount);
}
var n = 3;
var bCount = 1, cCount = 2;
document.write(countStr(n,bCount,cCount));
</script>
|
Output :
19
Time Complexity : O(n)
Auxiliary Space : O(n)
Thanks to Mr. Lazy for suggesting above solutions.
A solution that works in O(1) time :
We can apply the concepts of combinatorics to solve this problem in constant time. we may recall the formula that the number of ways we can arrange a total of n objects, out of which p number of objects are of one type, q objects are of another type, and r objects are of third type is n!/(p!q!r!)
Let us proceed towards the solution step by step.
How many strings we can form with no ‘b’ and ‘c’ ? Answer is 1 because we can arrange a string consisting only ‘a’ in one way only and the string would be aaaa….(n times) .
How many strings we can form with one ‘b’ ? Answer is n because we can arrange a string consisting (n-1) ‘a’s and 1 ‘b’ is n!/(n-1)! = n . Same goes for ‘c’ .
How many strings we can form with 2 places , filled up by ‘b’ and/or ‘c’ ? Answer is n*(n-1) + n*(n-1)/2 . Because, that 2 place can be either 1 ‘b’ and 1 ‘c’ or 2 ‘c’ according to our given constrains. For first case, total number of arrangements is n!/(n-2)! = n*(n-1) and for second case that is n!/(2!(n-2)!) = n*(n-1)/2 .
Finally, how many strings we can form with 3 places , filled up by ‘b’ and/or ‘c’ ? Answer is (n-2)*(n-1)*n/2 . Because, that 3 place can only be consisting of 1 ‘b’ and 2’c’ according to our given constrains. So, total number of arrangements is n!/(2!(n-3)!) = (n-2)*(n-1)*n/2 .
C++
#include<bits/stdc++.h>
using namespace std;
int countStr( int n){
int count = 0;
if (n>=1){
count += 1;
count += n;
count += n;
if (n>=2){
count += n*(n-1);
count += n*(n-1)/2;
if (n>=3){
count += (n-2)*(n-1)*n/2;
}
}
}
return count;
}
int main()
{
int n = 3;
cout << countStr(n);
return 0;
}
|
Java
import java.io.*;
class GFG
{
static int countStr( int n)
{
return 1 + (n * 2 ) +
(n * ((n * n) - 1 ) / 2 );
}
public static void main (String[] args)
{
int n = 3 ;
System.out.println( countStr(n));
}
}
|
Python 3
def countStr(n):
return ( 1 + (n * 2 ) +
(n * ((n * n) - 1 ) / / 2 ))
if __name__ = = "__main__" :
n = 3
print (countStr(n))
|
C#
using System;
class GFG
{
static int countStr( int n)
{
return 1 + (n * 2) +
(n * ((n * n) - 1) / 2);
}
static public void Main ()
{
int n = 3;
Console.WriteLine(countStr(n));
}
}
|
PHP
<?php
function countStr( $n )
{
return 1 + ( $n * 2) + ( $n *
(( $n * $n ) - 1) / 2);
}
$n = 3;
echo countStr( $n );
?>
|
Javascript
<script>
function countStr(n) {
return 1 + (n * 2) + (n * ((n * n) - 1) / 2);
}
var n = 3;
document.write(countStr(n));
</script>
|
Output :
19
Time Complexity : O(1)
Auxiliary Space : O(1)
Thanks to Niharika Sahai for providing above solution.
Reference :
https://careercup.appspot.com/question?id=5717453712654336
This article is contributed by Nishant Singh. If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.