Prerequisites: Dynamic Programming, DigitDP
Given two integers N and K. The task is to find the number of integers between 1 and N (inclusive) that contains exactly K non-zero digits when written in base ten.
Examples:
Input: N = 100, K = 1
Output: 19
Explanation:
The digits with exactly 1 non zero digits between 1 and 100 are:
1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 20, 30, 40, 50, 60, 70, 80, 90, 100Input: N = 25, K = 2
Output: 14
Explanation:
The digits with exactly 2 non zero digits between 1 and 25 are:
11, 12, 13, 14, 15, 16, 17,
18, 19, 21, 22, 23, 24, 25
Approach: It is enough to consider the integers of N digits, by filling the higher digits with 0 if necessary. This problem can be solved by applying the method called digit DP.
- dp[i][0][j] = The higher i digits have already been decided, and there are j non-zero digits, and it has already been determined that it is less than N.
- dp[i][1][j] = The higher i digits have already been decided, and there are j non-zero digits, and it has not yet been determined that it is less than N.
After computing the above dp, the desired answer is dp[L][0][K] + dp[L][1][K], where L is the number of digits of N.
Below is the implementation of the above approach:
C++
// C++ implementation of the above approach #include <bits/stdc++.h> using namespace std; // Function to find number less than N // having k non-zero digits int k_nonzero_numbers(string s, int n, int k) { // Store the memorised values int dp[n + 1][2][k + 1]; // Initialise for ( int i = 0; i <= n; i++) for ( int j = 0; j < 2; j++) for ( int x = 0; x <= k; x++) dp[i][j][x] = 0; // Base dp[0][0][0] = 1; // Calculate all states // For every state, from numbers 1 to N, // the count of numbers which contain exactly j // non zero digits is being computed and updated // in the dp array. for ( int i = 0; i < n; ++i) { int sm = 0; while (sm < 2) { for ( int j = 0; j < k + 1; ++j) { int x = 0; while (x <= (sm ? 9 : s[i] - '0' )) { dp[i + 1][sm || x < (s[i] - '0' )][j + (x > 0)] += dp[i][sm][j]; ++x; } } ++sm; } } // Return the required answer return dp[n][0][k] + dp[n][1][k]; } // Driver code int main() { string s = "25" ; int k = 2; int n = s.size(); // Function call cout << k_nonzero_numbers(s, n, k); return 0; } |
Java
// Java implementation of the above approach class Geeks{ // Function to find number less than N // having k non-zero digits static int k_nonzero_numbers(String s, int n, int k) { // Store the memorised values int dp[][][] = new int [n + 1 ][ 2 ][k + 1 ]; // Initialise for ( int i = 0 ; i <= n; i++) for ( int j = 0 ; j < 2 ; j++) for ( int x = 0 ; x <= k; x++) dp[i][j][x] = 0 ; // Base dp[ 0 ][ 0 ][ 0 ] = 1 ; // Calculate all states // For every state, from numbers 1 to N, // the count of numbers which contain exactly j // non zero digits is being computed and updated // in the dp array. for ( int i = 0 ; i < n; ++i) { int sm = 0 ; while (sm < 2 ) { for ( int j = 0 ; j < k + 1 ; ++j) { int x = 0 ; while (x <= (sm != 0 ? 9 :s.charAt(i) - '0' )) { if (j + (x > 0 ? 1 : 0 ) < k + 1 ) { dp[i + 1 ][(sm != 0 || x < (s.charAt(i) - '0' )) ? 1 : 0 ][j + (x > 0 ? 1 : 0 )] += dp[i][sm][j]; } ++x; } } ++sm; } } // Return the required answer return dp[n][ 0 ][k] + dp[n][ 1 ][k]; } // Driver code public static void main(String[] args) { String s = "25" ; int k = 2 ; int n = s.length(); // Function call System.out.println(k_nonzero_numbers(s, n, k)); } } // This code is contributed by Rajnis09 |
Python3
# Python3 implementation of the above approach # Function to find number less than N # having k non-zero digits def k_nonzero_numbers(s, n, k): # Store the memorised values dp = [[[ 0 for i in range (k + 2 )] for i in range ( 2 )] for i in range (n + 2 )] # Initialise for i in range (n + 1 ): for j in range ( 2 ): for x in range (k + 1 ): dp[i][j][x] = 0 # Base dp[ 0 ][ 0 ][ 0 ] = 1 # Calculate all states # For every state, from numbers 1 to N, # the count of numbers which contain # exactly j non zero digits is being # computed and updated in the dp array. for i in range (n): sm = 0 while (sm < 2 ): for j in range (k + 1 ): x = 0 y = 0 if sm: y = 9 else : y = ord (s[i]) - ord ( '0' ) while (x < = y): dp[i + 1 ][(sm or x < ( ord (s[i]) - ord ( '0' )))][j + (x > 0 )] + = dp[i][sm][j] x + = 1 sm + = 1 # Return the required answer return dp[n][ 0 ][k] + dp[n][ 1 ][k] # Driver code if __name__ = = '__main__' : s = "25" k = 2 n = len (s) # Function call print (k_nonzero_numbers(s, n, k)) # This code is contributed by mohit kumar 29 |
C#
// C# implementation of the above approach using System; using System.Collections; class GFG{ // Function to find number less than N // having k non-zero digits static int k_nonzero_numbers( string s, int n, int k) { // Store the memorised values int [,,]dp = new int [n + 1, 2, k + 1]; // Initialise for ( int i = 0; i <= n; i++) for ( int j = 0; j < 2; j++) for ( int x = 0; x <= k; x++) dp[i, j, x] = 0; // Base dp[0, 0, 0] = 1; // Calculate all states // For every state, from numbers 1 to N, // the count of numbers which contain exactly j // non zero digits is being computed and updated // in the dp array. for ( int i = 0; i < n; ++i) { int sm = 0; while (sm < 2) { for ( int j = 0; j < k + 1; ++j) { int x = 0; while (x <= (sm != 0 ? 9 : s[i]- '0' )) { if (j + (x > 0 ? 1 : 0) < k + 1) { dp[i + 1, ((sm != 0 || x < (s[i] - '0' )) ? 1 : 0), j + (x > 0 ? 1 : 0)] += dp[i, sm, j]; } ++x; } } ++sm; } } // Return the required answer return dp[n, 0, k] + dp[n, 1, k]; } // Driver code public static void Main( string [] args) { string s = "25" ; int k = 2; int n = s.Length; // Function call Console.Write(k_nonzero_numbers(s, n, k)); } } // This code is contributed by rutvik_56 |
Javascript
<script> // Javascript implementation of the above approach // Function to find number less than N // having k non-zero digits function k_nonzero_numbers(s,n,k) { // Store the memorised values let dp = new Array(n + 1); // Initialise for (let i = 0; i <= n; i++) { dp[i]= new Array(2); for (let j = 0; j < 2; j++) { dp[i][j] = new Array(k+1); for (let x = 0; x <= k; x++) dp[i][j][x] = 0; } } // Base dp[0][0][0] = 1; // Calculate all states // For every state, from numbers 1 to N, // the count of numbers which contain exactly j // non zero digits is being computed and updated // in the dp array. for (let i = 0; i < n; ++i) { let sm = 0; while (sm < 2) { for (let j = 0; j < k + 1; ++j) { let x = 0; while (x <= (sm != 0 ? 9 :s[i].charCodeAt(0) - '0' .charCodeAt(0))) { if (j + (x > 0 ? 1 : 0) < k + 1) { dp[i + 1][(sm != 0 || x < (s[i].charCodeAt(0) - '0' .charCodeAt(0))) ? 1 : 0][j + (x > 0 ? 1 : 0)] += dp[i][sm][j]; } ++x; } } ++sm; } } // Return the required answer return dp[n][0][k] + dp[n][1][k]; } // Driver code let s = "25" ; let k = 2; let n = s.length; // Function call document.write(k_nonzero_numbers(s, n, k)); // This code is contributed by unknown2108 </script> |
14
Time Complexity: O(LK) where L is the number of digits in N.
Auxiliary Space: O(N * K * 2)
Note: The two for loops used to calculate the state which form [0, 1] and [0, 9] respectively are considered as a constant multiplication.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!