Given a set of digits A[] in sorted order and two integers N and K, the task is to find how many numbers of length N are possible whose value is less than K and the digits are from the given set only. Note that you can use the same digit multiple times.
Examples:
Input: A[] = {0, 1, 5}, N = 1, K = 2
Output: 2
Only valid numbers are 0 and 1.Input: A[] = {0, 1, 2, 5}, N = 2, K = 21
Output: 5
10, 11, 12, 15 and 20 are the valid numbers.
Approach: Let d be the size of A[]. We can break this problem into three simpler cases.
- When N is greater than the length of K, It is obvious that if the length of N is greater than the length of k or if d is equal to 0, no such number is possible.
- When N is smaller than the length of K, then all possible combinations of digit of length N are valid. Also, we have to keep in mind that 0 can’t be in the first place. So, if A[] contains 0, the first place can be filled in (d – 1) ways. Since repetition is allowed and 0 can occupy the other places, rest N – 1 places can be filled in d * d * … * d(N – 1) times i.e. in dN – 1 ways. Therefore the answer is (d – 1) * (dN – 1) if A[] contains 0 else dN.
- When N is equal to the length of K, this is the trickiest part. We need to use Dynamic Programming for this part. Construct a digit array of K. Let’s call it digit[]. Let First(i) be the number formed by taking the first i digits of it. Let lower[i] denote the number of elements in A[] which are smaller than i.
For example, First(2) of 423 is 42. If A[] = {0, 2} then lower[0] = 0, lower[1] = 1, lower[2] = 1, lower[3] = 2.
Generate N digit numbers by dynamic programming. Let dp[i] denote total numbers of length i which are less than first i digits of K.
Elements in dp[i] can be generated by two cases:- For all the numbers whose First(i – 1) is less than First(i – 1) of K, we can put any digit at ith index. Hence, dp[i] = dp[i] + (dp[i – 1] * d)
- For all the numbers whose First(i – 1) is the same as First(i – 1) of K, we can only put those digits which are smaller than digit[i]. Hence, dp[i] = dp[i] + lower[digit[i]].
Below is the implementation of the above approach:
C++14
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; #define MAX 10 // Function to convert a number into vector vector< int > numToVec( int N) { vector< int > digit; // Push all the digits of N from the end // one by one to the vector while (N != 0) { digit.push_back(N % 10); N = N / 10; } // If the original number was 0 if (digit.size() == 0) digit.push_back(0); // Reverse the vector elements reverse(digit.begin(), digit.end()); // Return the required vector return digit; } // Function to return the count of B length integers // which are less than C and they // contain digits from set A[] only int solve(vector< int >& A, int B, int C) { vector< int > digit; int d, d2; // Convert number to digit array digit = numToVec(C); d = A.size(); // Case 1: No such number possible as the // generated numbers will always // be greater than C if (B > digit.size() || d == 0) return 0; // Case 2: All integers of length B are valid // as they all are less than C else if (B < digit.size()) { // contain 0 if (A[0] == 0 && B != 1) return (d - 1) * pow (d, B - 1); else return pow (d, B); } // Case 3 else { int dp[B + 1] = { 0 }; int lower[MAX + 1] = { 0 }; // Update the lower[] array such that // lower[i] stores the count of elements // in A[] which are less than i for ( int i = 0; i < d; i++) lower[A[i] + 1] = 1; for ( int i = 1; i <= MAX; i++) lower[i] = lower[i - 1] + lower[i]; bool flag = true ; dp[0] = 0; for ( int i = 1; i <= B; i++) { d2 = lower[digit[i - 1]]; dp[i] = dp[i - 1] * d; // For first index we can't use 0 if (i == 1 && A[0] == 0 && B != 1) d2 = d2 - 1; // Whether (i-1) digit of generated number // can be equal to (i - 1) digit of C if (flag) dp[i] += d2; // Is digit[i - 1] present in A ? flag = (flag & (lower[digit[i - 1] + 1] == lower[digit[i - 1]] + 1)); } return dp[B]; } } // Driver code int main() { // Digits array vector< int > A = { 0, 1, 2, 5 }; int N = 2; int k = 21; cout << solve(A, N, k); return 0; } |
Java
// Java implementation of the approach import java.util.*; class GFG { static int MAX = 10 ; // Function to convert a number into vector static Vector<Integer> numToVec( int N) { Vector<Integer> digit = new Vector<Integer>(); // Push all the digits of N from the end // one by one to the vector while (N != 0 ) { digit.add(N % 10 ); N = N / 10 ; } // If the original number was 0 if (digit.size() == 0 ) digit.add( 0 ); // Reverse the vector elements Collections.reverse(digit); // Return the required vector return digit; } // Function to return the count // of B length integers which are // less than C and they contain // digits from set A[] only static int solve(Vector<Integer> A, int B, int C) { Vector<Integer> digit = new Vector<Integer>(); int d, d2; // Convert number to digit array digit = numToVec(C); d = A.size(); // Case 1: No such number possible as the // generated numbers will always // be greater than C if (B > digit.size() || d == 0 ) return 0 ; // Case 2: All integers of length B are valid // as they all are less than C else if (B < digit.size()) { // contain 0 if (A.get( 0 ) == 0 && B != 1 ) return ( int ) ((d - 1 ) * Math.pow(d, B - 1 )); else return ( int ) Math.pow(d, B); } // Case 3 else { int []dp = new int [B + 1 ]; int []lower = new int [MAX + 1 ]; // Update the lower[] array such that // lower[i] stores the count of elements // in A[] which are less than i for ( int i = 0 ; i < d; i++) lower[A.get(i) + 1 ] = 1 ; for ( int i = 1 ; i <= MAX; i++) lower[i] = lower[i - 1 ] + lower[i]; boolean flag = true ; dp[ 0 ] = 0 ; for ( int i = 1 ; i <= B; i++) { d2 = lower[digit.get(i - 1 )]; dp[i] = dp[i - 1 ] * d; // For first index we can't use 0 if (i == 1 && A.get( 0 ) == 0 && B != 1 ) d2 = d2 - 1 ; // Whether (i-1) digit of generated number // can be equal to (i - 1) digit of C if (flag) dp[i] += d2; // Is digit[i - 1] present in A ? flag = (flag & (lower[digit.get(i - 1 ) + 1 ] == lower[digit.get(i - 1 )] + 1 )); } return dp[B]; } } // Driver code public static void main(String[] args) { Integer arr[] = { 0 , 1 , 2 , 5 }; // Digits array Vector<Integer> A = new Vector<>(Arrays.asList(arr)); int N = 2 ; int k = 21 ; System.out.println(solve(A, N, k)); } } // This code is contributed // by PrinciRaj1992 |
Python3
# Python3 implementation of the approach MAX = 10 # Function to convert a number into vector def numToVec(N): digit = [] # Push all the digits of N from the end # one by one to the vector while (N ! = 0 ): digit.append(N % 10 ) N = N / / 10 # If the original number was 0 if ( len (digit) = = 0 ): digit.append( 0 ) # Reverse the vector elements digit = digit[:: - 1 ] # Return the required vector return digit # Function to return the count of B length integers # which are less than C and they # contain digits from set A[] only def solve(A, B, C): d, d2 = 0 , 0 # Convert number to digit array digit = numToVec(C) d = len (A) # Case 1: No such number possible as the # generated numbers will always # be greater than C if (B > len (digit) or d = = 0 ): return 0 # Case 2: All integers of length B are valid # as they all are less than C elif (B < len (digit)): # contain 0 if (A[ 0 ] = = 0 and B ! = 1 ): return (d - 1 ) * pow (d, B - 1 ) else : return pow (d, B) # Case 3 else : dp = [ 0 for i in range (B + 1 )] lower = [ 0 for i in range ( MAX + 1 )] # Update the lower[] array such that # lower[i] stores the count of elements # in A[] which are less than i for i in range (d): lower[A[i] + 1 ] = 1 for i in range ( 1 , MAX + 1 ): lower[i] = lower[i - 1 ] + lower[i] flag = True dp[ 0 ] = 0 for i in range ( 1 , B + 1 ): d2 = lower[digit[i - 1 ]] dp[i] = dp[i - 1 ] * d # For first index we can't use 0 if (i = = 1 and A[ 0 ] = = 0 and B ! = 1 ): d2 = d2 - 1 # Whether (i-1) digit of generated number # can be equal to (i - 1) digit of C if (flag): dp[i] + = d2 # Is digit[i - 1] present in A ? flag = (flag & (lower[digit[i - 1 ] + 1 ] = = lower[digit[i - 1 ]] + 1 )) return dp[B] # Driver code # Digits array A = [ 0 , 1 , 2 , 5 ] N = 2 k = 21 print (solve(A, N, k)) # This code is contributed by mohit kumar 29 |
C#
// C# implementation of the approach using System; using System.Collections.Generic; class GFG { static int MAX = 10; // Function to convert a number into vector static List< int > numToVec( int N) { List< int > digit = new List< int >(); // Push all the digits of N from the end // one by one to the vector while (N != 0) { digit.Add(N % 10); N = N / 10; } // If the original number was 0 if (digit.Count == 0) digit.Add(0); // Reverse the vector elements digit.Reverse(); // Return the required vector return digit; } // Function to return the count // of B length integers which are // less than C and they contain // digits from set A[] only static int solve(List< int > A, int B, int C) { List< int > digit = new List< int >(); int d, d2; // Convert number to digit array digit = numToVec(C); d = A.Count; // Case 1: No such number possible as the // generated numbers will always // be greater than C if (B > digit.Count || d == 0) return 0; // Case 2: All integers of length B are valid // as they all are less than C else if (B < digit.Count) { // contain 0 if (A[0] == 0 && B != 1) return ( int ) ((d - 1) * Math.Pow(d, B - 1)); else return ( int ) Math.Pow(d, B); } // Case 3 else { int []dp = new int [B + 1]; int []lower = new int [MAX + 1]; // Update the lower[] array such that // lower[i] stores the count of elements // in A[] which are less than i for ( int i = 0; i < d; i++) lower[A[i] + 1] = 1; for ( int i = 1; i <= MAX; i++) lower[i] = lower[i - 1] + lower[i]; Boolean flag = true ; dp[0] = 0; for ( int i = 1; i <= B; i++) { d2 = lower[digit[i-1]]; dp[i] = dp[i - 1] * d; // For first index we can't use 0 if (i == 1 && A[0] == 0 && B != 1) d2 = d2 - 1; // Whether (i-1) digit of generated number // can be equal to (i - 1) digit of C if (flag) dp[i] += d2; // Is digit[i - 1] present in A ? flag = (flag & (lower[digit[i-1] + 1] == lower[digit[i-1]] + 1)); } return dp[B]; } } // Driver code public static void Main(String[] args) { int []arr = { 0, 1, 2, 5 }; // Digits array List< int > A = new List< int >(arr); int N = 2; int k = 21; Console.WriteLine(solve(A, N, k)); } } // This code is contributed by Rajput-Ji |
Javascript
<script> // Javascript implementation of the approach let MAX = 10; // Function to convert a number into vector function numToVec(N) { let digit = []; // Push all the digits of N from the end // one by one to the vector while (N != 0) { digit.push(N % 10); N = Math.floor(N / 10); } // If the original number was 0 if (digit.length == 0) digit.push(0); // Reverse the vector elements digit.reverse(); // Return the required vector return digit; } // Function to return the count // of B length integers which are // less than C and they contain // digits from set A[] only function solve(A, B, C) { let digit = []; let d, d2; // Convert number to digit array digit = numToVec(C); d = A.length; // Case 1: No such number possible as the // generated numbers will always // be greater than C if (B > digit.length || d == 0) return 0; // Case 2: All integers of length B are valid // as they all are less than C else if (B < digit.length) { // contain 0 if (A[0] == 0 && B != 1) return Math.floor((d - 1) * Math.pow(d, B - 1)); else return Math.floor(Math.pow(d, B)); } // Case 3 else { let dp = new Array(B + 1); let lower = new Array(MAX + 1); for (let i = 0; i < dp.length; i++) { dp[i] = 0; } for (let i = 0; i < lower.length; i++) { lower[i] = 0; } // Update the lower[] array such that // lower[i] stores the count of elements // in A[] which are less than i for (let i = 0; i < d; i++) lower[A[i] + 1] = 1; for (let i = 1; i <= MAX; i++) lower[i] = lower[i - 1] + lower[i]; let flag = true ; dp[0] = 0; for (let i = 1; i <= B; i++) { d2 = lower[digit[i - 1]]; dp[i] = dp[i - 1] * d; // For first index we can't use 0 if (i == 1 && A[0] == 0 && B != 1) d2 = d2 - 1; // Whether (i-1) digit of generated number // can be equal to (i - 1) digit of C if (flag) dp[i] += d2; // Is digit[i - 1] present in A ? flag = (flag & (lower[digit[i - 1] + 1] == lower[digit[i - 1]] + 1)); } return dp[B]; } } // Driver code let arr = [ 0, 1, 2, 5 ]; let N = 2; let k = 21; document.write(solve(arr, N, k)); // This code is contributed by patel2127 </script> |
5
Time complexity: O(N)
Auxiliary Space: O(N), since N extra space has been taken.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!