Find the numbers from 1 to N that contains exactly k non-zero digits
Last Updated :
27 Feb, 2023
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, 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++
#include <bits/stdc++.h>
using namespace std;
int k_nonzero_numbers(string s, int n, int k)
{
int dp[n + 1][2][k + 1];
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;
dp[0][0][0] = 1;
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 dp[n][0][k] + dp[n][1][k];
}
int main()
{
string s = "25" ;
int k = 2;
int n = s.size();
cout << k_nonzero_numbers(s, n, k);
return 0;
}
|
Java
class Geeks{
static int k_nonzero_numbers(String s, int n, int k)
{
int dp[][][] = new int [n + 1 ][ 2 ][k + 1 ];
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 ;
dp[ 0 ][ 0 ][ 0 ] = 1 ;
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 dp[n][ 0 ][k] + dp[n][ 1 ][k];
}
public static void main(String[] args)
{
String s = "25" ;
int k = 2 ;
int n = s.length();
System.out.println(k_nonzero_numbers(s, n, k));
}
}
|
Python3
def k_nonzero_numbers(s, n, k):
dp = [[[ 0 for i in range (k + 2 )]
for i in range ( 2 )]
for i in range (n + 2 )]
for i in range (n + 1 ):
for j in range ( 2 ):
for x in range (k + 1 ):
dp[i][j][x] = 0
dp[ 0 ][ 0 ][ 0 ] = 1
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 dp[n][ 0 ][k] + dp[n][ 1 ][k]
if __name__ = = '__main__' :
s = "25"
k = 2
n = len (s)
print (k_nonzero_numbers(s, n, k))
|
C#
using System;
using System.Collections;
class GFG{
static int k_nonzero_numbers( string s, int n,
int k)
{
int [,,]dp = new int [n + 1, 2, k + 1];
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;
dp[0, 0, 0] = 1;
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 dp[n, 0, k] + dp[n, 1, k];
}
public static void Main( string [] args)
{
string s = "25" ;
int k = 2;
int n = s.Length;
Console.Write(k_nonzero_numbers(s, n, k));
}
}
|
Javascript
<script>
function k_nonzero_numbers(s,n,k)
{
let dp = new Array(n + 1);
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;
}
}
dp[0][0][0] = 1;
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 dp[n][0][k] + dp[n][1][k];
}
let s = "25" ;
let k = 2;
let n = s.length;
document.write(k_nonzero_numbers(s, n, k));
</script>
|
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.
Share your thoughts in the comments
Please Login to comment...