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

24 Nov, 2021
Prerequisites: Dynamic Programming, DigitDPGiven 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, 100
Input: 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++
Java
Python3
C#
Javascript
// 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 implementation of the above approachclass 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 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# 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
<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 from [0, 1] and [0, 9] respectively are considered as a constant multiplication. 
Rajnis09
rutvik_56
mohit kumar 29
unknown2108
rishavmahato348
Dynamic Programming
Mathematical
Dynamic Programming
Mathematical
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Bellman–Ford Algorithm | DP-23
Floyd Warshall Algorithm | DP-16
Subset Sum Problem | DP-25
Coin Change | DP-7
Matrix Chain Multiplication | DP-8
Write a program to print all permutations of a given string
C++ Data Types
Set in C++ Standard Template Library (STL)
Coin Change | DP-7
Merge two sorted arrays