Given a positive integer N, the task is to count the number of N-digit numbers such that every digit from [0-9] occurs at least once.
Examples :
Input: N = 10
Output : 3265920
Input: N = 5
Output: 0
Explanation: Since the number of digits is less than the minimum number of digits required [0-9], the answer is 0.
Naive Approach: The simplest approach to solve the problem is to generate over all possible N-digit numbers and for each such number, check if all its digits satisfy the required condition or not.
Time Complexity: O(10N*N)
Auxiliary Space: O(1)
Efficient Approach: To optimize the above approach, the idea is to use Dynamic Programming as it has overlapping subproblems and optimal substructure. The subproblems can be stored in dp[][] table using memoization, where dp[digit][mask] stores the answer from the digitth position till the end, when the included digits are represented using a mask.
Follow the steps below to solve this problem:
- Define a recursive function, say countOfNumbers(digit, mask), and perform the following steps:
- Base Case: If the value of digit is equal to N+1, then check if the value of the mask is equal to (1 << 10 – 1). If found to be true, return 1 as a valid N-digit number is formed.
- If the result of the state dp[digit][mask] is already computed, return this state dp[digit][mask].
- If the current position is 1, then any digit from [1-9] can be placed. If N is equal to 1, then 0 can be placed as well.
- For any other position, any digit from [0-9] can be placed.
- If a particular digit ‘i’ is included, then update mask as mask = mask | (1 << i ).
- After making a valid placement, recursively call the countOfNumbers function for index digit+1.
- Return the sum of all possible valid placements of digits as the answer.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
long long dp[100][1 << 10];
long long countOfNumbers( int digit,
int mask, int N)
{
if (digit == N + 1) {
if (mask == (1 << 10) - 1)
return 1;
return 0;
}
long long & val = dp[digit][mask];
if (val != -1)
return val;
val = 0;
if (digit == 1) {
for ( int i = (N == 1 ? 0 : 1); i <= 9; ++i) {
val += countOfNumbers(digit + 1,
mask | (1 << i), N);
}
}
else {
for ( int i = 0; i <= 9; ++i) {
val += countOfNumbers(digit + 1,
mask | (1 << i), N);
}
}
return val;
}
int main()
{
memset (dp, -1, sizeof dp);
int N = 10;
cout << countOfNumbers(1, 0, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int dp[][] = new int [ 100 ][ 1 << 10 ];
static long countOfNumbers( int digit,
int mask, int N)
{
if (digit == N + 1 ) {
if (mask == ( 1 << 10 ) - 1 )
return 1 ;
return 0 ;
}
long val = dp[digit][mask];
if (val != - 1 )
return val;
val = 0 ;
if (digit == 1 ) {
for ( int i = (N == 1 ? 0 : 1 ); i <= 9 ; ++i) {
val += countOfNumbers(digit + 1 ,
mask | ( 1 << i), N);
}
}
else {
for ( int i = 0 ; i <= 9 ; ++i) {
val += countOfNumbers(digit + 1 ,
mask | ( 1 << i), N);
}
}
return val;
}
public static void main(String[] args)
{
for ( int i = 0 ;i<dp.length;i++)
Arrays.fill(dp[i], - 1 );
int N = 10 ;
System.out.print(countOfNumbers( 1 , 0 , N));
}
}
|
Python3
dp = [[ - 1 for j in range ( 1 << 10 )] for i in range ( 100 )]
def countOfNumbers(digit, mask, N):
if (digit = = N + 1 ):
if (mask = = ( 1 << 10 ) - 1 ):
return 1
return 0
val = dp[digit][mask]
if (val ! = - 1 ):
return val
val = 0
if (digit = = 1 ):
for i in range (( 0 if (N = = 1 ) else 1 ), 10 ):
val + = countOfNumbers(digit + 1 , mask | ( 1 << i), N)
else :
for i in range ( 10 ):
val + = countOfNumbers(digit + 1 , mask | ( 1 << i), N)
return val
N = 10
print (countOfNumbers( 1 , 0 , N))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static long [][] dp = new long [100][];
static long countOfNumbers( int digit, int mask, int N)
{
if (digit == N + 1) {
if (mask == (1 << 10) - 1){
return 1;
}
return 0;
}
long val = dp[digit][mask];
if (val != -1){
return val;
}
val = 0;
if (digit == 1) {
for ( int i = (N == 1 ? 0 : 1) ; i <= 9 ; ++i) {
val += countOfNumbers(digit + 1, mask | (1 << i), N);
}
}
else {
for ( int i = 0; i <= 9; ++i) {
val += countOfNumbers(digit + 1, mask | (1 << i), N);
}
}
dp[digit][mask] = val;
return val;
}
public static void Main( string [] args){
for ( int i = 0 ; i < dp.Length ; i++){
dp[i] = new long [1 << 10];
for ( int j = 0 ; j < (1 << 10) ; j++){
dp[i][j] = -1;
}
}
int N = 10;
Console.Write(countOfNumbers(1, 0, N));
}
}
|
Javascript
<script>
let dp = new Array(100);
for (let i = 0; i < 100; i++) {
dp[i] = new Array(1 << 10).fill(-1);
}
function countOfNumbers(digit, mask, N)
{
if (digit == N + 1) {
if (mask == (1 << 10) - 1)
return 1;
return 0;
}
let val = dp[digit][mask];
if (val != -1)
return val;
val = 0;
if (digit == 1) {
for (let i = (N == 1 ? 0 : 1); i <= 9; ++i) {
val += countOfNumbers(digit + 1,
mask | (1 << i), N);
}
}
else {
for (let i = 0; i <= 9; ++i) {
val += countOfNumbers(digit + 1,
mask | (1 << i), N);
}
}
return val;
}
let N = 10;
document.write(countOfNumbers(1, 0, N));
</script>
|
Time Complexity: O(N2*210)
Auxiliary Space: O(N*210)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a DP to store the solution of the subproblems and initialize it with 0.\
- Initialize the DP with base cases dp[0][0] = 1.
- Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP
- Create a variable ans to store final result and iterate over DP and update ans.
- Return the final solution stored in ans.
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
long long countOfNumbers( int N) {
long long dp[N + 1][1 << 10];
memset (dp, 0, sizeof (dp));
dp[0][0] = 1;
for ( int digit = 1; digit <= N; ++digit) {
if (digit == 1) {
for ( int i = (N == 1 ? 0 : 1); i <= 9; ++i) {
for ( int mask = 0; mask < (1 << 10); ++mask) {
dp[digit][mask | (1 << i)] += dp[digit - 1][mask];
}
}
}
else {
for ( int i = 0; i <= 9; ++i) {
for ( int mask = 0; mask < (1 << 10); ++mask) {
dp[digit][mask | (1 << i)] += dp[digit - 1][mask];
}
}
}
}
long long ans = 0;
for ( int mask = 0; mask < (1 << 10); ++mask) {
if (mask == (1 << 10) - 1)
ans += dp[N][mask];
}
return ans;
}
int main()
{
int N = 10;
cout << countOfNumbers(N);
return 0;
}
|
Java
import java.util.Arrays;
public class GFG {
static long countOfNumbers( int N) {
long [][] dp = new long [N + 1 ][ 1 << 10 ];
for ( long [] row : dp) {
Arrays.fill(row, 0 );
}
dp[ 0 ][ 0 ] = 1 ;
for ( int digit = 1 ; digit <= N; ++digit) {
if (digit == 1 ) {
for ( int i = (N == 1 ? 0 : 1 ); i <= 9 ; ++i) {
for ( int mask = 0 ; mask < ( 1 << 10 ); ++mask) {
dp[digit][mask | ( 1 << i)] += dp[digit - 1 ][mask];
}
}
}
else {
for ( int i = 0 ; i <= 9 ; ++i) {
for ( int mask = 0 ; mask < ( 1 << 10 ); ++mask) {
dp[digit][mask | ( 1 << i)] += dp[digit - 1 ][mask];
}
}
}
}
long ans = 0 ;
for ( int mask = 0 ; mask < ( 1 << 10 ); ++mask) {
if (mask == ( 1 << 10 ) - 1 ) {
ans += dp[N][mask];
}
}
return ans;
}
public static void main(String[] args) {
int N = 10 ;
System.out.println(countOfNumbers(N));
}
}
|
Python
def countOfNumbers(N):
dp = [[ 0 ] * ( 1 << 10 ) for i in range (N + 1 )]
for i in range (N + 1 ):
for j in range ( 1 << 10 ):
dp[i][j] = 0
dp[ 0 ][ 0 ] = 1
for digit in range ( 1 , N + 1 ):
if digit = = 1 :
for i in range ( 0 if N = = 1 else 1 , 10 ):
for mask in range ( 1 << 10 ):
dp[digit][mask | ( 1 << i)] + = dp[digit - 1 ][mask]
else :
for i in range ( 10 ):
for mask in range ( 1 << 10 ):
dp[digit][mask | ( 1 << i)] + = dp[digit - 1 ][mask]
ans = 0
for mask in range ( 1 << 10 ):
if mask = = ( 1 << 10 ) - 1 :
ans + = dp[N][mask]
return ans
if __name__ = = '__main__' :
N = 10
print (countOfNumbers(N))
|
C#
using System;
public class GFG
{
public static long CountOfNumbers( int N)
{
long [,] dp = new long [N + 1, 1 << 10];
for ( int i = 0; i <= N; i++)
{
for ( int j = 0; j < (1 << 10); j++)
{
dp[i, j] = 0;
}
}
dp[0, 0] = 1;
for ( int digit = 1; digit <= N; digit++)
{
if (digit == 1)
{
for ( int i = (N == 1 ? 0 : 1); i <= 9; i++)
{
for ( int mask = 0; mask < (1 << 10); mask++)
{
dp[digit, mask | (1 << i)] += dp[digit - 1, mask];
}
}
}
else
{
for ( int i = 0; i <= 9; i++)
{
for ( int mask = 0; mask < (1 << 10); mask++)
{
dp[digit, mask | (1 << i)] += dp[digit - 1, mask];
}
}
}
}
long ans = 0;
for ( int mask = 0; mask < (1 << 10); mask++)
{
if (mask == (1 << 10) - 1)
ans += dp[N, mask];
}
return ans;
}
public static void Main()
{
int N = 10;
Console.WriteLine(CountOfNumbers(N));
}
}
|
Javascript
function countOfNumbers(N) {
let dp = new Array(N + 1);
for (let i = 0; i <= N; i++) {
dp[i] = new Array(1 << 10).fill(0);
}
dp[0][0] = 1;
for (let digit = 1; digit <= N; ++digit) {
if (digit === 1) {
for (let i = (N === 1 ? 0 : 1); i <= 9; ++i) {
for (let mask = 0; mask < (1 << 10); ++mask) {
dp[digit][mask | (1 << i)] += dp[digit - 1][mask];
}
}
}
else {
for (let i = 0; i <= 9; ++i) {
for (let mask = 0; mask < (1 << 10); ++mask) {
dp[digit][mask | (1 << i)] += dp[digit - 1][mask];
}
}
}
}
let ans = 0;
for (let mask = 0; mask < (1 << 10); ++mask) {
if (mask === (1 << 10) - 1) {
ans += dp[N][mask];
}
}
return ans;
}
let N = 10;
console.log(countOfNumbers(N));
|
Time Complexity: O(N * 2^10)
Auxiliary Space: O(N * 2^10)