Find the numbers from 1 to N that contains exactly k non-zero digits

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 digitsint 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 codeint 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 digitsstatic 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 codepublic 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 digitsdef 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 codeif __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 approachusing System;using System.Collections; class GFG{// Function to find number less than N// having k non-zero digitsstatic 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 codepublic 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 digitsfunction 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 codelet s = "25";let k = 2;let n = s.length;// Function calldocument.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 zambiatek!



