Total numbers with no repeated digits in a range
Given a range find total such numbers in the given range such that they have no repeated digits. For example: 12 has no repeated digit. 22 has repeated digit. 102, 194 and 213 have no repeated digit. 212, 171 and 4004 have repeated digits.
Examples:
Input : 10 12 Output : 2 Explanation : In the given range 10 and 12 have no repeated digit where as 11 has repeated digit. Input : 1 100 Output : 90
Brute Force We will traverse through each element in the given range and count the number of digits which do not have repeated digits.
C++
// C++ implementation of brute // force solution. #include <bits/stdc++.h> using namespace std; // Function to check if the given // number has repeated digit or not int repeated_digit( int n) { unordered_set< int > s; // Traversing through each digit while (n != 0) { int d = n % 10; // if the digit is present // more than once in the // number if (s.find(d) != s.end()) { // return 0 if the number // has repeated digit return 0; } s.insert(d); n = n / 10; } // return 1 if the number has // no repeated digit return 1; } // Function to find total number // in the given range which has // no repeated digit int calculate( int L, int R) { int answer = 0; // Traversing through the range for ( int i = L; i < R + 1; ++i) { // Add 1 to the answer if i has // no repeated digit else 0 answer = answer + repeated_digit(i); } return answer ; } // Driver Code int main() { int L = 1, R = 100; // Calling the calculate cout << calculate(L, R); return 0; } // This code is contributed by // Sanjit_Prasad |
Java
// Java implementation of brute // force solution. import java.util.LinkedHashSet; class GFG { // Function to check if the given // number has repeated digit or not static int repeated_digit( int n) { LinkedHashSet<Integer> s = new LinkedHashSet<>(); // Traversing through each digit while (n != 0 ) { int d = n % 10 ; // if the digit is present // more than once in the // number if (s.contains(d)) { // return 0 if the number // has repeated digit return 0 ; } s.add(d); n = n / 10 ; } // return 1 if the number has // no repeated digit return 1 ; } // Function to find total number // in the given range which has // no repeated digit static int calculate( int L, int R) { int answer = 0 ; // Traversing through the range for ( int i = L; i < R + 1 ; ++i) { // Add 1 to the answer if i has // no repeated digit else 0 answer = answer + repeated_digit(i); } return answer; } // Driver Code public static void main(String[] args) { int L = 1 , R = 100 ; // Calling the calculate System.out.println(calculate(L, R)); } } // This code is contributed by RAJPUT-JI |
Python3
# Python implementation of brute # force solution. # Function to check if the given # number has repeated digit or not def repeated_digit(n): a = [] # Traversing through each digit while n ! = 0 : d = n % 10 # if the digit is present # more than once in the # number if d in a: # return 0 if the number # has repeated digit return 0 a.append(d) n = n / / 10 # return 1 if the number has no # repeated digit return 1 # Function to find total number # in the given range which has # no repeated digit def calculate(L,R): answer = 0 # Traversing through the range for i in range (L,R + 1 ): # Add 1 to the answer if i has # no repeated digit else 0 answer = answer + repeated_digit(i) # return answer return answer # Driver's Code L = 1 R = 100 # Calling the calculate print (calculate(L, R)) |
C#
// C# implementation of brute // force solution. using System; using System.Collections.Generic; class GFG { // Function to check if the given // number has repeated digit or not static int repeated_digit( int n) { var s = new HashSet< int >(); // Traversing through each digit while (n != 0) { int d = n % 10; // if the digit is present // more than once in the // number if (s.Contains(d)) { // return 0 if the number // has repeated digit return 0; } s.Add(d); n = n / 10; } // return 1 if the number has // no repeated digit return 1; } // Function to find total number // in the given range which has // no repeated digit static int calculate( int L, int R) { int answer = 0; // Traversing through the range for ( int i = L; i < R + 1; ++i) { // Add 1 to the answer if i has // no repeated digit else 0 answer = answer + repeated_digit(i); } return answer; } // Driver Code public static void Main(String[] args) { int L = 1, R = 100; // Calling the calculate Console.WriteLine(calculate(L, R)); } } // This code is contributed by RAJPUT-JI |
PHP
<?php // PHP implementation of // brute force solution. // Function to check if // the given number has // repeated digit or not function repeated_digit( $n ) { $c = 10; $a = array_fill (0, $c , 0); // Traversing through // each digit while ( $n > 0) { $d = $n % 10; // if the digit is present // more than once in the // number if ( $a [ $d ] > 0) { // return 0 if the number // has repeated digit return 0; } $a [ $d ]++; $n = (int)( $n / 10); } // return 1 if the number // has no repeated digit return 1; } // Function to find total // number in the given range // which has no repeated digit function calculate( $L , $R ) { $answer = 0; // Traversing through // the range for ( $i = $L ; $i <= $R ; $i ++) { // Add 1 to the answer if // i has no repeated digit // else 0 $answer += repeated_digit( $i ); } // return answer return $answer ; } // Driver Code $L = 1; $R = 100; // Calling the calculate echo calculate( $L , $R ); // This code is contributed by mits ?> |
Javascript
// JS implementation of brute // force solution. // Function to check if the given // number has repeated digit or not function repeated_digit(n) { let s = new Set(); // Traversing through each digit while (n != 0) { let d = n % 10; // if the digit is present // more than once in the // number if (s.has(d)) { // return 0 if the number // has repeated digit return 0; } s.add(d); n = Math.floor(n / 10); } // return 1 if the number has // no repeated digit return 1; } // Function to find total number // in the given range which has // no repeated digit function calculate(L, R) { let answer = 0; // Traversing through the range for ( var i = L; i < R + 1; ++i) { // Add 1 to the answer if i has // no repeated digit else 0 answer = answer + repeated_digit(i); } return answer ; } // Driver Code let L = 1, R = 100; // Calling the calculate console.log(calculate(L, R)) // This code is contributed by // phasing17 |
90
This method will answer each query in O( N ) time.
Auxiliary Space: O(log(N))
Efficient Approach
We will calculate a prefix array of the numbers which have no repeated digit. = Total number with no repeated digit less than or equal to 1. Therefore each query can be solved in O(1) time.
Below is the implementation of above idea.
C++
// C++ implementation of above idea #include <bits/stdc++.h> using namespace std; // Maximum int MAX = 1000; // Prefix Array vector< int > Prefix = {0}; // Function to check if the given // number has repeated digit or not int repeated_digit( int n) { unordered_set< int > a; int d; // Traversing through each digit while (n != 0) { d = n % 10; // if the digit is present // more than once in the // number if (a.find(d) != a.end()) // return 0 if the number // has repeated digit return 0; a.insert(d); n = n / 10; } // return 1 if the number has no // repeated digit return 1; } // Function to pre calculate // the Prefix array void pre_calculation( int MAX) { Prefix.push_back(repeated_digit(1)); // Traversing through the numbers // from 2 to MAX for ( int i = 2; i < MAX + 1; i++) // Generating the Prefix array Prefix.push_back(repeated_digit(i) + Prefix[i-1]); } // Calculate Function int calculate( int L, int R) { // Answer return Prefix[R] - Prefix[L-1]; } // Driver code int main() { int L = 1, R = 100; // Pre-calculating the Prefix array. pre_calculation(MAX); // Calling the calculate function // to find the total number of number // which has no repeated digit cout << calculate(L, R) << endl; return 0; } // This code is contributed by Rituraj Jain |
Java
// Java implementation of above idea import java.util.*; class GFG { // Maximum static int MAX = 100 ; // Prefix Array static Vector<Integer> Prefix = new Vector<>(); // Function to check if the given // number has repeated digit or not static int repeated_digit( int n) { HashSet<Integer> a = new HashSet<>(); int d; // Traversing through each digit while (n != 0 ) { d = n % 10 ; // if the digit is present // more than once in the // number if (a.contains(d)) // return 0 if the number // has repeated digit return 0 ; a.add(d); n /= 10 ; } // return 1 if the number has no // repeated digit return 1 ; } // Function to pre calculate // the Prefix array static void pre_calculations() { Prefix.add( 0 ); Prefix.add(repeated_digit( 1 )); // Traversing through the numbers // from 2 to MAX for ( int i = 2 ; i < MAX + 1 ; i++) // Generating the Prefix array Prefix.add(repeated_digit(i) + Prefix.elementAt(i - 1 )); } // Calculate Function static int calculate( int L, int R) { // Answer return Prefix.elementAt(R) - Prefix.elementAt(L - 1 ); } // Driver Code public static void main(String[] args) { int L = 1 , R = 100 ; // Pre-calculating the Prefix array. pre_calculations(); // Calling the calculate function // to find the total number of number // which has no repeated digit System.out.println(calculate(L, R)); } } // This code is contributed by // sanjeev2552 |
Python3
# Python implementation of # above idea # Prefix Array Prefix = [ 0 ] # Function to check if # the given number has # repeated digit or not def repeated_digit(n): a = [] # Traversing through each digit while n ! = 0 : d = n % 10 # if the digit is present # more than once in the # number if d in a: # return 0 if the number # has repeated digit return 0 a.append(d) n = n / / 10 # return 1 if the number has no # repeated digit return 1 # Function to pre calculate # the Prefix array def pre_calculation( MAX ): # To use to global Prefix array global Prefix Prefix.append(repeated_digit( 1 )) # Traversing through the numbers # from 2 to MAX for i in range ( 2 , MAX + 1 ): # Generating the Prefix array Prefix.append( repeated_digit(i) + Prefix[i - 1 ] ) # Calculate Function def calculate(L,R): # Answer return Prefix[R] - Prefix[L - 1 ] # Driver Code # Maximum MAX = 1000 # Pre-calculating the Prefix array. pre_calculation( MAX ) # Range L = 1 R = 100 # Calling the calculate function # to find the total number of number # which has no repeated digit print (calculate(L, R)) |
C#
// C# implementation of above idea using System; using System.Collections.Generic; class GFG { // Maximum static int MAX = 100; // Prefix Array static List< int > Prefix = new List< int >(); // Function to check if the given // number has repeated digit or not static int repeated_digit( int n) { HashSet< int > a = new HashSet< int >(); int d; // Traversing through each digit while (n != 0) { d = n % 10; // if the digit is present // more than once in the // number if (a.Contains(d)) // return 0 if the number // has repeated digit return 0; a.Add(d); n /= 10; } // return 1 if the number has no // repeated digit return 1; } // Function to pre calculate // the Prefix array static void pre_calculations() { Prefix.Add(0); Prefix.Add(repeated_digit(1)); // Traversing through the numbers // from 2 to MAX for ( int i = 2; i < MAX + 1; i++) // Generating the Prefix array Prefix.Add(repeated_digit(i) + Prefix[i - 1]); } // Calculate Function static int calculate( int L, int R) { // Answer return Prefix[R] - Prefix[L - 1]; } // Driver Code public static void Main(String[] args) { int L = 1, R = 100; // Pre-calculating the Prefix array. pre_calculations(); // Calling the calculate function // to find the total number of number // which has no repeated digit Console.WriteLine(calculate(L, R)); } } // This code is contributed by 29AjayKumar |
JavaScript
<script> // JavaScript implementation of brute // force solution. // Function to check if the given // number has repeated digit or not function repeated_digit(n){ const s = new Set(); // Traversing through each digit while (n != 0){ let d = n % 10; // if the digit is present // more than once in the // number if (s.has(d)){ // return 0 if the number // has repeated digit return 0; } s.add(d); n = Math.floor(n / 10); } // return 1 if the number has // no repeated digit return 1; } // Function to find total number // in the given range which has // no repeated digit function calculate(L, R){ let answer = 0; // Traversing through the range for (let i = L; i < R + 1; ++i){ // Add 1 to the answer if i has // no repeated digit else 0 answer = answer + repeated_digit(i); } return answer ; } // Driver Code { let L = 1, R = 100; // Calling the calculate console.log(calculate(L, R)); } // This code is contributed by Gautam goel (gautamgoel962) </script> |
90
Efficient Approach: The above approach can be optimized based on the following idea:
Dynamic programming can be used to solve this problem
- dp[i][j][k][l] represents numbers in the range with i’th position to be filled, j represents tight condition, k represents bitmask set for each digit from 0 to 9 and l represents whether previously non zero digit number taken or not.
- It can be observed that the recursive function is called exponential times. That means that some states are called repeatedly.
So the idea is to store the value of each state. This can be done using by store the value of a state and whenever the function is called, return the stored value without computing again.
- First answer will be calculated for 0 to A – 1 and then calculated for 0 to B then latter one is subtracted with prior one to get answer for range [L, R]
Follow the steps below to solve the problem:
- Create a recursive function that takes four parameters i representing the position to be filled, j representing the tight condition, k representing bitmask and l representing whether previously non zero digit taken or not.
- Call the recursive function for choosing all digits from 0 to 9 apart from N.
- Base case if N size digit formed return 1;
- Create a 2d array dp[N][2][M][2] initially filled with -1.
- If the answer for a particular state is computed then save it in dp[i][j][k][l].
- If the answer for a particular state is already computed then just return dp[i][j][k][l].
Below is the implementation of the above approach:
C++
// C++ code to implement the approach #include <bits/stdc++.h> using namespace std; // DP table initialized with -1 int dp[11][2][(1LL << 10) - 1][2]; // Recursive Function to find numbers // in the range L to R such that its // digits are distinct int recur( int i, int j, int k, int l, string a) { // Base case if (i == a.size()) { return 1; } // If answer for current state is already // calculated then just return dp[i][j][k] if (dp[i][j][k][l] != -1) return dp[i][j][k][l]; // Answer initialized with zero int ans = 0; // Tight condition true if (j == 1) { // Iterating from 0 to max value of // tight condition for ( int digit = 0; digit <= 9; digit++) { // mask for digit int mask = (1 << digit); // if that digit is available to use if (mask & k) { // calling recursive function for max digit // taken and retaining tight condition if (digit == (( int )a[i] - 48)) { ans += recur(i + 1, 1, k - (1 << digit), 1, a); } // calling recursive function for zero // and dropping tight condition else if (digit == 0) { ans += recur(i + 1, 0, k, 0, a); } // calling recursive function for number // less than max and dropping condition else if (digit < (( int )a[i] - 48)) { ans += recur(i + 1, 0, k - (1 << digit), 1, a); } } } } // Tight condition false else { // Iterating for all digits for ( int digit = 0; digit <= 9; digit++) { int mask = (1 << digit); if (mask & k) { // calling recursive function for // not taking anything if (digit == 0 and l == 0) ans += recur(i + 1, 0, k, 0, a); // calling recursive function for // taking zero else if (digit == 0 and l == 1) ans += recur(i + 1, 0, k - (1 << digit), 1, a); // calling recursive function for taking // digits from 1 to 9 else ans += recur(i + 1, 0, k - (1 << digit), 1, a); } } } // Save and return dp value return dp[i][j][k][l] = ans; } // Function to find numbers // in the range L to R such that its // digits are distinct int countInRange( int A, int B) { // Initializing dp array with - 1 memset (dp, -1, sizeof (dp)); A--; string L = to_string(A), R = to_string(B); // Numbers with distinct digits in range 0 to L int ans1 = recur(0, 1, (1 << 10) - 1, 0, L); // Initializing dp array with - 1 memset (dp, -1, sizeof (dp)); // Numbers with distinct digits in range 0 to R int ans2 = recur(0, 1, (1 << 10) - 1, 0, R); // Difference of ans2 and ans1 // will generate answer for required range return ans2 - ans1; } // Driver Code int main() { // Input 1 int L = 1, R = 100; // Function Call cout << countInRange(L, R) << endl; return 0; } |
Java
// Java code to implement the approach import java.util.*; class GFG { // DP table initialized with -1 static int [][][][] dp = new int [ 11 ][ 2 ][( 1 << 10 )][ 2 ]; // Recursive Function to find numbers // in the range L to R such that its // digits are distinct static int recur( int i, int j, int k, int l, String a) { // Base case if (i == a.length()) { return 1 ; } // If answer for current state is already // calculated then just return dp[i][j][k] if (dp[i][j][k][l] != - 1 ) return dp[i][j][k][l]; // Answer initialized with zero int ans = 0 ; // Tight condition true if (j == 1 ) { // Iterating from 0 to max value of // tight condition for ( int digit = 0 ; digit <= 9 ; digit++) { // mask for digit int mask = ( 1 << digit); // if that digit is available to use if ((mask & k) != 0 ) { // calling recursive function for max // digit taken and retaining tight // condition if (digit == (( int )a.charAt(i) - 48 )) { ans += recur(i + 1 , 1 , k - ( 1 << digit), 1 , a); } // calling recursive function for zero // and dropping tight condition else if (digit == 0 ) { ans += recur(i + 1 , 0 , k, 0 , a); } // calling recursive function for number // less than max and dropping condition else if (digit < (( int )a.charAt(i) - 48 )) { ans += recur(i + 1 , 0 , k - ( 1 << digit), 1 , a); } } } } // Tight condition false else { // Iterating for all digits for ( int digit = 0 ; digit <= 9 ; digit++) { int mask = ( 1 << digit); if ((mask & k) != 0 ) { // calling recursive function for // not taking anything if (digit == 0 && l == 0 ) ans += recur(i + 1 , 0 , k, 0 , a); // calling recursive function for // taking zero else if (digit == 0 && l == 1 ) ans += recur(i + 1 , 0 , k - ( 1 << digit), 1 , a); // calling recursive function for taking // digits from 1 to 9 else ans += recur(i + 1 , 0 , k - ( 1 << digit), 1 , a); } } } // Save and return dp value return dp[i][j][k][l] = ans; } // Function to find numbers // in the range L to R such that its // digits are distinct static int countInRange( int A, int B) { // Initializing dp array with - 1 for ( int [][][] table : dp) { for ( int [][] row : table) { for ( int [] innerRow : row) { Arrays.fill(innerRow, - 1 ); } } } A--; String L = String.valueOf(A); String R = String.valueOf(B); // Numbers with distinct digits in range 0 to L int ans1 = recur( 0 , 1 , ( 1 << 10 ) - 1 , 0 , L); // Initializing dp array with - 1 for ( int [][][] table : dp) { for ( int [][] row : table) { for ( int [] innerRow : row) { Arrays.fill(innerRow, - 1 ); } } } // Numbers with distinct digits in range 0 to R int ans2 = recur( 0 , 1 , ( 1 << 10 ) - 1 , 0 , R); // Difference of ans2 and ans1 // will generate answer for required range return ans2 - ans1; } // Driver Code public static void main(String[] args) { // Input 1 int L = 1 , R = 100 ; // Function Call System.out.println(countInRange(L, R)); } } |
Python3
# Python code to implement the approach # DP table initialized with -1 dp = [[[[ - 1 for l in range ( 2 )] for k in range ( 1 << 10 )] for j in range ( 2 )] for i in range ( 11 )] def memset(dp): for i in range ( 11 ): for j in range ( 2 ): for k in range ( 1 << 10 ): for l in range ( 2 ): dp[i][j][k][l] = - 1 # Recursive Function to find numbers # in the range L to R such that its # digits are distinct def recur(i, j, k, l, a): # Base case if i = = len (a): return 1 # If answer for current state is already # calculated then just return dp[i][j][k] if dp[i][j][k][l] ! = - 1 : return dp[i][j][k][l] # Answer initialized with zero ans = 0 # Tight condition true if j = = 1 : # Iterating from 0 to max value of # tight condition for digit in range ( 10 ): # mask for digit mask = ( 1 << digit) # if that digit is available to use if mask & k: # calling recursive function for max digit # taken and retaining tight condition if digit = = int (a[i]): ans + = recur(i + 1 , 1 , k - ( 1 << digit), 1 , a) # calling recursive function for zero # and dropping tight condition elif digit = = 0 : ans + = recur(i + 1 , 0 , k, 0 , a) # calling recursive function for number # less than max and dropping condition elif digit < int (a[i]): ans + = recur(i + 1 , 0 , k - ( 1 << digit), 1 , a) # Tight condition false else : # Iterating for all digits for digit in range ( 10 ): mask = ( 1 << digit) if mask & k: # calling recursive function for # not taking anything if digit = = 0 and l = = 0 : ans + = recur(i + 1 , 0 , k, 0 , a) # calling recursive function for # taking zero elif digit = = 0 and l = = 1 : ans + = recur(i + 1 , 0 , k - ( 1 << digit), 1 , a) # calling recursive function for taking # digits from 1 to 9 else : ans + = recur(i + 1 , 0 , k - ( 1 << digit), 1 , a) dp[i][j][k][l] = ans # Save and return dp value return ans # Function to find numbers # in the range L to R such that its # digits are distinct def countInRange(A, B): # Initializing dp array with - 1 memset(dp) A - = 1 L = str (A) R = str (B) # Numbers with distinct digits in range 0 to ans1 = recur( 0 , 1 , ( 1 << 10 ) - 1 , 0 , L) # Initializing dp array with - 1 memset(dp) # Numbers with distinct digits in range 0 to R ans2 = recur( 0 , 1 , ( 1 << 10 ) - 1 , 0 , R) # Difference of ans2 and ans1 # will generate answer for required range return ans2 - ans1 # Driver Code # Input 1 L = 1 R = 100 # Function Call print (countInRange(L, R)) # This code is contributed by prajwalkandekar123. |
C#
// C# code to implement the approach using System; public class GFG { // DP table initialized with -1 static int [,,,] dp = new int [11, 2, (1 << 10), 2]; // Recursive Function to find numbers // in the range L to R such that its // digits are distinct static int recur( int i, int j, int k, int l, String a) { // Base case if (i == a.Length) { return 1; } // If answer for current state is already // calculated then just return dp[i][j][k] if (dp[i, j, k, l] != -1) return dp[i, j, k, l]; // Answer initialized with zero int ans = 0; // Tight condition true if (j == 1) { // Iterating from 0 to max value of // tight condition for ( int digit = 0; digit <= 9; digit++) { // mask for digit int mask = (1 << digit); // if that digit is available to use if ((mask & k) != 0) { // calling recursive function for max // digit taken and retaining tight // condition if (digit == (( int )a[i] - 48)) { ans += recur(i + 1, 1, k - (1 << digit), 1, a); } // calling recursive function for zero // and dropping tight condition else if (digit == 0) { ans += recur(i + 1, 0, k, 0, a); } // calling recursive function for number // less than max and dropping condition else if (digit < (( int )a[i] - 48)) { ans += recur(i + 1, 0, k - (1 << digit), 1, a); } } } } // Tight condition false else { // Iterating for all digits for ( int digit = 0; digit <= 9; digit++) { int mask = (1 << digit); if ((mask & k) != 0) { // calling recursive function for // not taking anything if (digit == 0 && l == 0) ans += recur(i + 1, 0, k, 0, a); // calling recursive function for // taking zero else if (digit == 0 && l == 1) ans += recur(i + 1, 0, k - (1 << digit), 1, a); // calling recursive function for taking // digits from 1 to 9 else ans += recur(i + 1, 0, k - (1 << digit), 1, a); } } } // Save and return dp value return dp[i, j, k, l] = ans; } // Function to find numbers // in the range L to R such that its // digits are distinct static int countInRange( int A, int B) { // Initializing dp array with - 1 for ( int i = 0; i < dp.GetLength(0); i++) { for ( int j = 0; j < dp.GetLength(1); j++) { for ( int k = 0; k < dp.GetLength(2); k++) { for ( int l = 0; l < dp.GetLength(3); l++) { dp[i, j, k, l] = -1; } } } } A--; String L = A.ToString(); String R = B.ToString(); // Numbers with distinct digits in range 0 to L int ans1 = recur(0, 1, (1 << 10) - 1, 0, L); // Initializing dp array with - 1 for ( int i = 0; i < dp.GetLength(0); i++) { for ( int j = 0; j < dp.GetLength(1); j++) { for ( int k = 0; k < dp.GetLength(2); k++) { for ( int l = 0; l < dp.GetLength(3); l++) { dp[i, j, k, l] = -1; } } } } // Numbers with distinct digits in range 0 to R int ans2 = recur(0, 1, (1 << 10) - 1, 0, R); // Difference of ans2 and ans1 // will generate answer for required range return ans2 - ans1; } // Driver Code public static void Main(String[] args) { // Input 1 int L = 1, R = 100; // Function Call Console.WriteLine(countInRange(L, R)); } } |
Javascript
// Javascript code to implement the approach // DP table initialized with -1 //int dp[11][2][(1LL << 10) - 1][2]; let dp= new Array(11); for (let i=0; i<11; i++) { dp[i]= new Array(2); for (let j=0; j<2; j++) { dp[i][j]= new Array(1<<10); for (let k=0; k<(1<<10); k++) dp[i][j][k]= new Array(2); } } function memset(dp) { for (let i=0; i<11; i++) { for (let j=0; j<2; j++) { for (let k=0; k<(1<<10); k++) for (let l=0; l<2; l++) dp[i][j][k][l]=-1; } } } // Recursive Function to find numbers // in the range L to R such that its // digits are distinct function recur(i, j, k, l, a) { // Base case if (i == a.length) { return 1; } // If answer for current state is already // calculated then just return dp[i][j][k] if (dp[i][j][k][l] != -1) return dp[i][j][k][l]; // Answer initialized with zero let ans = 0; // Tight condition true if (j == 1) { // Iterating from 0 to max value of // tight condition for (let digit = 0; digit <= 9; digit++) { // mask for digit let mask = (1 << digit); // if that digit is available to use if (mask & k) { // calling recursive function for max digit // taken and retaining tight condition if (digit == (parseInt(a[i]))) { ans += recur(i + 1, 1, k - (1 << digit), 1, a); } // calling recursive function for zero // and dropping tight condition else if (digit == 0) { ans += recur(i + 1, 0, k, 0, a); } // calling recursive function for number // less than max and dropping condition else if (digit < (parseInt(a[i]))) { ans += recur(i + 1, 0, k - (1 << digit), 1, a); } } } } // Tight condition false else { // Iterating for all digits for (let digit = 0; digit <= 9; digit++) { let mask = (1 << digit); if (mask & k) { // calling recursive function for // not taking anything if (digit == 0 && l == 0) ans += recur(i + 1, 0, k, 0, a); // calling recursive function for // taking zero else if (digit == 0 && l == 1) ans += recur(i + 1, 0, k - (1 << digit), 1, a); // calling recursive function for taking // digits from 1 to 9 else ans += recur(i + 1, 0, k - (1 << digit), 1, a); } } } // Save and return dp value return dp[i][j][k][l] = ans; } // Function to find numbers // in the range L to R such that its // digits are distinct function countInRange(A, B) { // Initializing dp array with - 1 memset(dp); A--; let L = A.toString(), R = B.toString(); // Numbers with distinct digits in range 0 to L let ans1 = recur(0, 1, (1 << 10) - 1, 0, L); // Initializing dp array with - 1 memset(dp); // Numbers with distinct digits in range 0 to R let ans2 = recur(0, 1, (1 << 10) - 1, 0, R); // Difference of ans2 and ans1 // will generate answer for required range return ans2 - ans1; } // Driver Code // Input 1 let L = 1, R = 100; // Function Call console.log(countInRange(L, R)); |
90
Time Complexity: O(log(R – L) * M)
Auxiliary Space: O(log(R – L) * M)
Where M is the all possible subsets of set containing all digits from 0 to 9 for bitmask M = 1024
Related Articles:
- Introduction to Dynamic Programming – Data Structures and Algorithms Tutorials
- Bitmasking and Dynamic Programming
Please Login to comment...