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
Explanation:
Number of strings with 3 occurrances of a: 1
2-a and 1-b: 3
2-a and 1-c: 3
1-a, 1-b and 1-c: 6
1-a and 2-c: 3
1-b and 2-c: 3
So, total number of strings of length 3
is 1 + 3 + 3 + 6 + 3 + 3 = 19Input: n = 1
Output: 3
Explanation: Possible strings are: "a", "b" and "c"
Table of Content
[Naive Approach] Recursion (Generate All Valid Strings) - O(3^n) Time O(n) Space
A simple solution is to recursively build strings by choosing
'a','b', or'c'at each step while keeping track of remaining allowed counts of'b'and'c'.
// C++ program to count number of strings
#include<bits/stdc++.h>
using namespace std;
// n is total number of characters.
// bCount and cCount are counts of 'b'
// and 'c' respectively.
int countStrUtil(int n, int bCount, int cCount)
{
// Base cases
if (bCount < 0 || cCount < 0) return 0;
if (n == 0) return 1;
if (bCount == 0 && cCount == 0) return 1;
// Three cases, we choose, a or b or c
// In all three cases n decreases by 1.
int res = countStrUtil(n-1, bCount, cCount);
res += countStrUtil(n-1, bCount-1, cCount);
res += countStrUtil(n-1, bCount, cCount-1);
return res;
}
// Wrapper function
int countStr(int n)
{
int bCount = 1, cCount = 2;
return countStrUtil(n, bCount, cCount);
}
// Driver code
int main()
{
int n = 3;
cout << countStr(n);
return 0;
}
import java.util.*;
public class Main {
// n is total number of characters.
// bCount and cCount are counts of 'b'
// and 'c' respectively.
static int countStrUtil(int n, int bCount, int cCount) {
// Base cases
if (bCount < 0 || cCount < 0) return 0;
if (n == 0) return 1;
if (bCount == 0 && cCount == 0) return 1;
// Three cases, we choose, a or b or c
// In all three cases n decreases by 1.
int res = countStrUtil(n-1, bCount, cCount);
res += countStrUtil(n-1, bCount-1, cCount);
res += countStrUtil(n-1, bCount, cCount-1);
return res;
}
// Wrapper function
static int countStr(int n) {
int bCount = 1, cCount = 2;
return countStrUtil(n, bCount, cCount);
}
// Driver code
public static void main(String[] args) {
int n = 3;
System.out.println(countStr(n));
}
}
def countStrUtil(n, bCount, cCount):
# Base cases
if bCount < 0 or cCount < 0: return 0
if n == 0: return 1
if bCount == 0 and cCount == 0: return 1
# Three cases, we choose, a or b or c
# In all three cases n decreases by 1.
res = countStrUtil(n-1, bCount, cCount)
res += countStrUtil(n-1, bCount-1, cCount)
res += countStrUtil(n-1, bCount, cCount-1)
return res
# Wrapper function
def countStr(n):
bCount = 1
cCount = 2
return countStrUtil(n, bCount, cCount)
# Calling main function
if __name__ == "__main__":
n = 3
print(countStr(n))
using System;
public class Program {
// n is total number of characters.
// bCount and cCount are counts of 'b'
// and 'c' respectively.
static int countStrUtil(int n, int bCount, int cCount) {
// Base cases
if (bCount < 0 || cCount < 0) return 0;
if (n == 0) return 1;
if (bCount == 0 && cCount == 0) return 1;
// Three cases, we choose, a or b or c
// In all three cases n decreases by 1.
int res = countStrUtil(n-1, bCount, cCount);
res += countStrUtil(n-1, bCount-1, cCount);
res += countStrUtil(n-1, bCount, cCount-1);
return res;
}
// Wrapper function
static int countStr(int n) {
int bCount = 1, cCount = 2;
return countStrUtil(n, bCount, cCount);
}
// Driver code
public static void Main() {
int n = 3;
Console.WriteLine(countStr(n));
}
}
function countStrUtil(n, bCount, cCount) {
// Base cases
if (bCount < 0 || cCount < 0) return 0;
if (n === 0) return 1;
if (bCount === 0 && cCount === 0) return 1;
// Three cases, we choose, a or b or c
// In all three cases n decreases by 1.
let res = countStrUtil(n-1, bCount, cCount);
res += countStrUtil(n-1, bCount-1, cCount);
res += countStrUtil(n-1, bCount, cCount-1);
return res;
}
// Wrapper function
function countStr(n) {
let bCount = 1;
let cCount = 2;
return countStrUtil(n, bCount, cCount);
}
const n = 3;
console.log(countStr(n));
Output
19
[Better Approach] Recursion + Memoization (DP) - O(n)Â Time O(n) Space
Use recursion with a DP array to store already computed states
(n, bCount, cCount)and reuse them to avoid repeated calculations.
// C++ program to count number of strings
#include<bits/stdc++.h>
using namespace std;
// n is total number of characters.
// bCount and cCount are counts of 'b'
// and 'c' respectively.
long long countStrUtil(long long dp[][2][3], int n, int bCount=1,
int cCount=2)
{
// Base cases
if (bCount < 0 || cCount < 0) return 0;
if (n == 0) return 1;
if (bCount == 0 && cCount == 0) return 1;
// if we had saw this combination previously
if (dp[n][bCount][cCount] != -1)
return dp[n][bCount][cCount];
// Three cases, we choose, a or b or c
// In all three cases n decreases by 1.
long long 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);
}
// A wrapper over countStrUtil()
long long countStr(int n)
{
long long dp[n+1][2][3];
memset(dp, -1, sizeof(dp));
return countStrUtil(dp, n);
}
// Driver code
int main()
{
int n = 3;
cout << countStr(n);
return 0;
}
#include <stdio.h>
#include <string.h>
// n is total number of characters.
// bCount and cCount are counts of 'b'
// and 'c' respectively.
int countStrUtil(int dp[101][2][3], int n, int bCount, int cCount)
{
// Base cases
if (bCount < 0 || cCount < 0) return 0;
if (n == 0) return 1;
if (bCount == 0 && cCount == 0) return 1;
// if we had saw this combination previously
if (dp[n][bCount][cCount]!= -1)
return dp[n][bCount][cCount];
// Three cases, we choose, a or b or c
// In all three cases n decreases by 1.
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);
}
// A wrapper over countStrUtil()
int countStr(int n)
{
int dp[101][2][3];
memset(dp, -1, sizeof(dp));
return countStrUtil(dp, n, 1, 2);
}
// Driver code
int main()
{
int n = 3;
printf("%d", countStr(n));
return 0;
}
public class GfG {
// n is total number of characters.
// bCount and cCount are counts of 'b'
// and 'c' respectively.
static int countStrUtil(int dp[][][], int n, int bCount, int cCount) {
// Base cases
if (bCount < 0 || cCount < 0) return 0;
if (n == 0) return 1;
if (bCount == 0 && cCount == 0) return 1;
// if we had saw this combination previously
if (dp[n][bCount][cCount]!= -1)
return dp[n][bCount][cCount];
// Three cases, we choose, a or b or c
// In all three cases n decreases by 1.
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);
}
// A wrapper over countStrUtil()
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, 1, 2);
}
// Driver code
public static void main (String[] args) {
int n = 3;
System.out.println(countStr(n));
}
}
def countStrUtil(dp, n, bCount, cCount):
# Base cases
if bCount < 0 or cCount < 0: return 0
if n == 0: return 1
if bCount == 0 and cCount == 0: return 1
# if we had saw this combination previously
if dp[n][bCount][cCount]!= -1:
return dp[n][bCount][cCount]
# Three cases, we choose, a or b or c
# In all three cases n decreases by 1.
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 res
# A wrapper over countStrUtil()
def countStr(n):
dp = [[[-1 for _ in range(3)] for _ in range(2)] for _ in range(n+1)]
return countStrUtil(dp, n, 1, 2)
# Driver code
if __name__ == '__main__':
n = 3
print(countStr(n))
// C# program to count number of strings
// of n characters with
using System;
class GFG
{
// n is total number of characters.
// bCount and cCount are counts of 'b'
// and 'c' respectively.
static int countStrUtil(int[,,] dp, int n,
int bCount=1, int cCount=2)
{
// Base cases
if (bCount < 0 || cCount < 0)
return 0;
if (n == 0)
return 1;
if (bCount == 0 && cCount == 0)
return 1;
// if we had saw this combination previously
if (dp[n,bCount,cCount] != -1)
return dp[n,bCount,cCount];
// Three cases, we choose, a or b or c
// In all three cases n decreases by 1.
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);
}
// A wrapper over countStrUtil()
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);
}
// Driver code
static void Main()
{
int n = 3;
Console.Write(countStr(n));
}
}
// This code is contributed by DrRoot_
// javascript program to count number of strings
function countStrUtil(dp, n, bCount, cCount)
{
// Base cases
if (bCount < 0 || cCount < 0) return 0;
if (n == 0) return 1;
if (bCount == 0 && cCount == 0) return 1;
// Check DP
if (dp[n][bCount][cCount] != -1)
return dp[n][bCount][cCount];
// three choices: a, b, c
let 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;
}
// Wrapper function
function countStr(n, bCount, cCount)
{
let dp = Array.from({ length: n + 1 }, () =>
Array.from({ length: 2 }, () =>
Array(3).fill(-1)
)
);
return countStrUtil(dp, n, bCount, cCount);
}
// Driver code
let n = 3;
let bCount = 1, cCount = 2;
console.log(countStr(n, bCount, cCount));
Output
19
[Expected Approach] Combinatorics Solution - O(1) Time O(1) Space
The idea is to use 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 the third type is n ! /( p! q! r!)
How many strings we can form with no 'b' and 'c'?
The answer is 1 because we can arrange a string consisting of only 'a' in one way only and the string would be aaaa....(n times).
How many strings we can form with one 'b' and 'a's?
The answer is n because we can arrange a string consisting (n-1) 'a's and 1 'b' is n! / (n - 1)! = n. The same goes for 'c' .
How many strings we can form with only 2 places filled up by 'b' and/or 'c' ? Â
Answer is n * (n - 1) + n * (n - 1)/2 . Because that 2 places can be either 1 'b' and 1 'c' Â or 2 'c' according to our given constraints. For the 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 1 'b' and/or 2 'c' ? Â
Answer is (n - 2)*(n - 1)*n /2 . Because those 3 places can only be consisting of 1 'b' and 2'c' Â according to our given constraints. So, total number of arrangements is n! /(2! (n - 3)!) = (n - 2) * (n - 1) * n/2 .
// program to find number of strings
// that can be made under given constraints.
#include<bits/stdc++.h>
using namespace std;
long long int countStr(long long int n) {
long long int count = 0;
if(n >= 1){
// aaa...
count += 1;
// one 'b'
count += n;
// one 'c'
count += n;
if(n >= 2){
// one 'b' and one 'c'
count += n * (n - 1);
// two 'c'
count += (n * (n - 1)) / 2;
if(n >= 3){
// one 'b' and two 'c'
count += (n * (n - 1) * (n - 2)) / 2;
}
}
}
return count;
}
// Driver code
int main()
{
int n = 3;
cout << countStr(n);
return 0;
}
#include <stdio.h>
int countStr(int n) {
int count = 0;
if (n >= 1) {
//aaa...
count += 1;
//b...aaa...
count += n;
//c...aaa...
count += n;
if (n >= 2) {
//bc...aaa...
count += n * (n - 1);
//cc...aaa...
count += n * (n - 1) / 2;
if (n >= 3) {
//bcc...aaa...
count += (n - 2) * (n - 1) * n / 2;
}
}
}
return count;
}
int main() {
int n = 3;
printf("%d", countStr(n));
return 0;
}
public class GfG {
public static int countStr(int n) {
int count = 0;
if (n >= 1) {
//aaa...
count += 1;
//b...aaa...
count += n;
//c...aaa...
count += n;
if (n >= 2) {
//bc...aaa...
count += n * (n - 1);
//cc...aaa...
count += n * (n - 1) / 2;
if (n >= 3) {
//bcc...aaa...
count += (n - 2) * (n - 1) * n / 2;
}
}
}
return count;
}
public static void main(String[] args) {
int n = 3;
System.out.println(countStr(n));
}
}
def countStr(n):
count = 0
if n >= 1:
#aaa...
count += 1
#b...aaa...
count += n
#c...aaa...
count += n
if n >= 2:
#bc...aaa...
count += n * (n - 1)
#cc...aaa...
count += n * (n - 1) // 2
if n >= 3:
#bcc...aaa...
count += (n - 2) * (n - 1) * n // 2
return count
# Driver code
n = 3
print(countStr(n))
using System;
public class GfG
{
public static int countStr(int n)
{
int count = 0;
if (n >= 1)
{
//aaa...
count += 1;
//b...aaa...
count += n;
//c...aaa...
count += n;
if (n >= 2)
{
//bc...aaa...
count += n * (n - 1);
//cc...aaa...
count += n * (n - 1) / 2;
if (n >= 3)
{
//bcc...aaa...
count += (n - 2) * (n - 1) * n / 2;
}
}
}
return count;
}
public static void Main()
{
int n = 3;
Console.WriteLine(countStr(n));
}
}
function countStr(n) {
let count = 0;
if (n >= 1) {
//aaa...
count += 1;
//b...aaa...
count += n;
//c...aaa...
count += n;
if (n >= 2) {
//bc...aaa...
count += n * (n - 1);
//cc...aaa...
count += Math.floor(n * (n - 1) / 2);
if (n >= 3) {
//bcc...aaa...
count += Math.floor((n - 2) * (n - 1) * n / 2);
}
}
}
return count;
}
// Driver code
let n = 3;
console.log(countStr(n));
<?php
function countStr($n) {
$count = 0;
if ($n >= 1) {
//aaa...
$count += 1;
//b...aaa...
$count += $n;
//c...aaa...
$count += $n;
if ($n >= 2) {
//bc...aaa...
$count += $n * ($n - 1);
//cc...aaa...
$count += $n * ($n - 1) / 2;
if ($n >= 3) {
//bcc...aaa...
$count += ($n - 2) * ($n - 1) * $n / 2;
}
}
}
return $count;
}
// Driver code
$n = 3;
echo countStr($n);
?>
Output
19