Given two integers N and K, the task is to find the count of all the integer in base K which satisfy the following conditions:
- The integers must be of exactly N digits.
- There should be no leading 0.
- There must not be any consecutive digit pair such that both the digits are 0.
Examples:
Input: N = 3, K = 10
Output: 891
All 3-digit numbers in base 10 are from the range [100, 999]
Out of these numbers only 100, 200, 300, 400, ..., 900 are invalid.
Hence valid integers are 900 - 9 = 891
Input: N = 2, K = 10
Output: 90
Naive approach: Write a function count_numbers(int k, int n, bool flag) which will return the count of N digit numbers possible of base K and flag will tell whether the previously chosen digit was 0 or not. Call this function recursively for count_numbers(int k, int n-1, bool flag), and using the flag, the occurrence of two consecutive 0s can be avoided.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int count_numbers( int k, int n, bool flag)
{
if (n == 1) {
if (flag) {
return (k - 1);
}
else {
return 1;
}
}
if (flag)
return (k - 1) * (count_numbers(k, n - 1, 0)
+ count_numbers(k, n - 1, 1));
else
return count_numbers(k, n - 1, 1);
}
int main()
{
int n = 3;
int k = 10;
cout << count_numbers(k, n, true );
return 0;
}
|
Java
class GFG
{
static int count_numbers( int k, int n,
boolean flag)
{
if (n == 1 )
{
if (flag)
{
return (k - 1 );
}
else
{
return 1 ;
}
}
if (flag)
return (k - 1 ) * (count_numbers(k, n - 1 , false ) +
count_numbers(k, n - 1 , true ));
else
return count_numbers(k, n - 1 , true );
}
public static void main (String[] args)
{
int n = 3 ;
int k = 10 ;
System.out.println(count_numbers(k, n, true ));
}
}
|
Python3
def count_numbers(k, n, flag) :
if (n = = 1 ) :
if (flag) :
return (k - 1 )
else :
return 1
if (flag) :
return (k - 1 ) * (count_numbers(k, n - 1 , 0 ) +
count_numbers(k, n - 1 , 1 ))
else :
return count_numbers(k, n - 1 , 1 )
n = 3
k = 10
print (count_numbers(k, n, True ))
|
C#
using System;
class GFG
{
static int count_numbers( int k, int n,
bool flag)
{
if (n == 1)
{
if (flag)
{
return (k - 1);
}
else
{
return 1;
}
}
if (flag)
return (k - 1) * (count_numbers(k, n - 1, false ) +
count_numbers(k, n - 1, true ));
else
return count_numbers(k, n - 1, true );
}
public static void Main (String[] args)
{
int n = 3;
int k = 10;
Console.Write(count_numbers(k, n, true ));
}
}
|
Javascript
<script>
function count_numbers(k, n, flag)
{
if (n == 1) {
if (flag) {
return (k - 1);
}
else {
return 1;
}
}
if (flag)
return (k - 1) * (count_numbers(k, n - 1, 0)
+ count_numbers(k, n - 1, 1));
else
return count_numbers(k, n - 1, 1);
}
let n = 3;
let k = 10;
document.write(count_numbers(k, n, true ));
</script>
|
Time Complexity: O(n2)
Auxiliary Space: O(n2)
Approach 2: Efficient
Now that the problem has been solved using recursion, a 2-D DP can be used to solve this problem dp[n + 1][2] where dp[i][0] will give the number of i digit numbers possible ending with 0 and dp[i][1] will give the number of i digit numbers possible ending with non-zero.
The recurrence relation will be:
dp[i][0] = dp[i - 1][1];
dp[i][1] = (dp[i - 1][0] + dp[i - 1][1]) * (K - 1);
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int count_numbers( int k, int n)
{
int dp[n + 1][2];
dp[1][0] = 0;
dp[1][1] = k - 1;
for ( int i = 2; i <= n; i++) {
dp[i][0] = dp[i - 1][1];
dp[i][1] = (dp[i - 1][0] + dp[i - 1][1]) * (k - 1);
}
return dp[n][0] + dp[n][1];
}
int main()
{
int k = 10;
int n = 3;
cout << count_numbers(k, n);
return 0;
}
|
Java
import java.util.*;
class GFG {
static int count_numbers( int k, int n)
{
int [][] dp = new int [n + 1 ][ 2 ];
dp[ 1 ][ 0 ] = 0 ;
dp[ 1 ][ 1 ] = k - 1 ;
for ( int i = 2 ; i <= n; i++) {
dp[i][ 0 ] = dp[i - 1 ][ 1 ];
dp[i][ 1 ]
= (dp[i - 1 ][ 0 ] + dp[i - 1 ][ 1 ]) * (k - 1 );
}
return dp[n][ 0 ] + dp[n][ 1 ];
}
public static void main(String[] args)
{
int k = 10 ;
int n = 3 ;
System.out.println(count_numbers(k, n));
}
}
|
Python3
def count_numbers(k, n):
dp = [[ 0 for i in range ( 2 )]
for i in range (n + 1 )]
dp[ 1 ][ 0 ] = 0
dp[ 1 ][ 1 ] = k - 1
for i in range ( 2 , n + 1 ):
dp[i][ 0 ] = dp[i - 1 ][ 1 ]
dp[i][ 1 ] = (dp[i - 1 ][ 0 ] +
dp[i - 1 ][ 1 ]) * (k - 1 )
return dp[n][ 0 ] + dp[n][ 1 ]
k = 10
n = 3
print (count_numbers(k, n))
|
C#
using System;
class GFG {
static int count_numbers( int k, int n)
{
int [, ] dp = new int [n + 1, 2];
dp[1, 0] = 0;
dp[1, 1] = k - 1;
for ( int i = 2; i <= n; i++) {
dp[i, 0] = dp[i - 1, 1];
dp[i, 1]
= (dp[i - 1, 0] + dp[i - 1, 1]) * (k - 1);
}
return dp[n, 0] + dp[n, 1];
}
public static void Main(String[] args)
{
int k = 10;
int n = 3;
Console.WriteLine(count_numbers(k, n));
}
}
|
Javascript
<script>
function count_numbers(k, n)
{
let dp = new Array(n + 1);
for (let i = 0; i < n + 1; i++)
dp[i] = new Array(2);
dp[1][0] = 0;
dp[1][1] = k - 1;
for (let i = 2; i <= n; i++) {
dp[i][0] = dp[i - 1][1];
dp[i][1] = (dp[i - 1][0] +
dp[i - 1][1]) * (k - 1);
}
return dp[n][0] + dp[n][1];
}
let k = 10;
let n = 3;
document.write(count_numbers(k, n));
</script>
|
Time Complexity: O(n)
Auxiliary Space: O(n)
Approach 3: More Efficient
Space optimize O(1)
In the previous approach, the current value dp[i] is only depend upon the previous values dp[i-1] .So to optimize the space complexity we can use variables to store current and previous computations instead of dp array of size n.
Implementation Steps:
- Initialize prev_zero to 0 and prev_nonzero to k-1.
- Loop from i=2 to i=n:
- Calculate curr_zero as prev_nonzero.
- Calculate curr_nonzero as (prev_zero + prev_nonzero) * (k-1).
- Update prev_zero to curr_zero and prev_nonzero to curr_nonzero.
- Return prev_zero + prev_nonzero.
Implementation:
C++
#include <iostream>
using namespace std;
int count_numbers( int k, int n)
{
int prev_zero = 0, prev_nonzero = k - 1, curr_zero,
curr_nonzero;
for ( int i = 2; i <= n; i++) {
curr_zero = prev_nonzero;
curr_nonzero = (prev_zero + prev_nonzero) * (k - 1);
prev_zero = curr_zero;
prev_nonzero = curr_nonzero;
}
return prev_zero + prev_nonzero;
}
int main()
{
int k = 10;
int n = 3;
cout << count_numbers(k, n) << endl;
return 0;
}
|
Java
public class Main {
public static int countNumbers( int k, int n)
{
int prevZero = 0 , prevNonZero = k - 1 ;
int currZero, currNonZero;
for ( int i = 2 ; i <= n; i++) {
currZero = prevNonZero;
currNonZero
= (prevZero + prevNonZero) * (k - 1 );
prevZero = currZero;
prevNonZero = currNonZero;
}
return prevZero + prevNonZero;
}
public static void main(String[] args)
{
int k = 10 ;
int n = 3 ;
System.out.println(countNumbers(k, n));
}
}
|
Python3
def count_numbers(k: int , n: int ) - > int :
prev_zero = 0
prev_nonzero = k - 1
curr_zero = 0
curr_nonzero = 0
for i in range ( 2 , n + 1 ):
curr_zero = prev_nonzero
curr_nonzero = (prev_zero + prev_nonzero) * (k - 1 )
prev_zero = curr_zero
prev_nonzero = curr_nonzero
return prev_zero + prev_nonzero
if __name__ = = '__main__' :
k = 10
n = 3
print (count_numbers(k, n))
|
C#
using System;
class CountNumbers
{
static int Count( int k, int n)
{
int prevZero = 0, prevNonZero = k - 1, currZero, currNonZero;
for ( int i = 2; i <= n; i++)
{
currZero = prevNonZero;
currNonZero = (prevZero + prevNonZero) * (k - 1);
prevZero = currZero;
prevNonZero = currNonZero;
}
return prevZero + prevNonZero;
}
static void Main()
{
int k = 10, n = 3;
Console.WriteLine(Count(k, n));
}
}
|
Javascript
function countNumbers(k, n)
{
let prevZero = 0, prevNonZero = k - 1;
let currZero, currNonZero;
for (let i = 2; i <= n; i++)
{
currZero = prevNonZero;
currNonZero = (prevZero + prevNonZero) * (k - 1);
prevZero = currZero;
prevNonZero = currNonZero;
}
return prevZero + prevNonZero;
}
const k = 10;
const n = 3;
console.log(countNumbers(k, n));
|
Output:
891
Time complexity: O(N)
Auxiliary Space: O(1)
Approach:
1. The code defines a function `isValid` that checks if a digit is valid based on the condition of not having a consecutive pair of zeros.
2. The `backtrack` function generates all possible combinations of digits for valid integers by recursively exploring each digit at each index, excluding leading zeros.
3. The `countValidIntegers` function initializes a count variable and calls the `backtrack` function to count the valid integers.
4. The main function initializes the values of N and K, calls `countValidIntegers`, and outputs the result.
Below is the implementation of the above approach:
C++
#include <iostream>
#include <vector>
using namespace std;
bool isValid( const vector< int >& number, int index, int digit);
void backtrack(vector< int >& number, int index, int N, int K, int & count) {
if (index == N) {
count++;
return ;
}
int start = (index == 0) ? 1 : 0;
for ( int digit = start; digit < K; digit++) {
if (isValid(number, index, digit)) {
number[index] = digit;
backtrack(number, index + 1, N, K, count);
}
}
}
bool isValid( const vector< int >& number, int index, int digit) {
if (index > 0 && number[index - 1] == 0 && digit == 0) {
return false ;
}
return true ;
}
int countValidIntegers( int N, int K) {
vector< int > number(N);
int count = 0;
backtrack(number, 0, N, K, count);
return count;
}
int main() {
int N = 3;
int K = 10;
int result = countValidIntegers(N, K);
cout << result << endl;
return 0;
}
|
Java
import java.util.Arrays;
public class GFG {
static boolean isValid( int [] number, int index, int digit) {
if (index > 0 && number[index - 1 ] == 0 && digit == 0 ) {
return false ;
}
return true ;
}
static void backtrack( int [] number, int index, int N, int K, int [] count) {
if (index == N) {
count[ 0 ]++;
return ;
}
int start = (index == 0 ) ? 1 : 0 ;
for ( int digit = start; digit < K; digit++) {
if (isValid(number, index, digit)) {
number[index] = digit;
backtrack(number, index + 1 , N, K, count);
}
}
}
static int countValidIntegers( int N, int K) {
int [] number = new int [N];
int [] count = new int [ 1 ];
backtrack(number, 0 , N, K, count);
return count[ 0 ];
}
public static void main(String[] args) {
int N = 3 ;
int K = 10 ;
int result = countValidIntegers(N, K);
System.out.println(result);
}
}
|
Python3
def is_valid(number, index, digit):
if index > 0 and number[index - 1 ] = = 0 and digit = = 0 :
return False
return True
def backtrack(number, index, N, K, count):
if index = = N:
count[ 0 ] + = 1
return
start = 1 if index = = 0 else 0
for digit in range (start, K):
if is_valid(number, index, digit):
number[index] = digit
backtrack(number, index + 1 , N, K, count)
def count_valid_integers(N, K):
number = [ 0 ] * N
count = [ 0 ]
backtrack(number, 0 , N, K, count)
return count[ 0 ]
N = 3
K = 10
result = count_valid_integers(N, K)
print (result)
|
C#
using System;
class Program {
static bool IsValid( int [] number, int index, int digit)
{
if (index > 0 && number[index - 1] == 0
&& digit == 0) {
return false ;
}
return true ;
}
static void Backtrack( int [] number, int index, int N,
int K, ref int count)
{
if (index == N) {
count++;
return ;
}
int start = (index == 0) ? 1 : 0;
for ( int digit = start; digit < K; digit++) {
if (IsValid(number, index, digit)) {
number[index] = digit;
Backtrack(number, index + 1, N, K,
ref count);
}
}
}
static int CountValidIntegers( int N, int K)
{
int [] number = new int [N];
int count = 0;
Backtrack(number, 0, N, K, ref count);
return count;
}
static void Main()
{
int N = 3;
int K = 10;
int result = CountValidIntegers(N, K);
Console.WriteLine(result);
}
}
|
Javascript
function isValid(number, index, digit) {
if (index > 0 && number[index - 1] === 0 && digit === 0) {
return false ;
}
return true ;
}
function backtrack(number, index, N, K, count) {
if (index === N) {
count[0]++;
return ;
}
const start = (index === 0) ? 1 : 0;
for (let digit = start; digit < K; digit++) {
if (isValid(number, index, digit)) {
number[index] = digit;
backtrack(number, index + 1, N, K, count);
}
}
}
function countValidIntegers(N, K) {
const number = new Array(N);
const count = [0];
backtrack(number, 0, N, K, count);
return count[0];
}
const N = 3;
const K = 10;
const result = countValidIntegers(N, K);
console.log(result);
|
Time Complexity: O(K^N)
The backtrack function is called recursively for each digit at each index, excluding leading zeros. The number of recursive calls depends on the value of N and K.
The number of possible digit choices at each index is K, so the total number of recursive calls is K^N.
As a result, the time complexity of the code is O(K^N), where K is the base and N is the number of digits.
Space Complexity:O(N)
The space complexity is determined by the space used by the number vector and the recursive calls.
The number vector stores the digits of the number and requires N units of space.
The recursive calls create a call stack, which can have a maximum depth of N.
Therefore, the space complexity of the code is O(N), where N is the number of digits