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++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; // Function to return the count of // n-digit numbers that satisfy // the given conditions int count_numbers( int k, int n, bool flag) { // Base case if (n == 1) { // If 0 wasn't chosen previously if (flag) { return (k - 1); } else { return 1; } } // If 0 wasn't chosen previously 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); } // Driver code int main() { int n = 3; int k = 10; cout << count_numbers(k, n, true ); return 0; } |
Java
// Java implementation of the approach class GFG { // Function to return the count of // n-digit numbers that satisfy // the given conditions static int count_numbers( int k, int n, boolean flag) { // Base case if (n == 1 ) { // If 0 wasn't chosen previously if (flag) { return (k - 1 ); } else { return 1 ; } } // If 0 wasn't chosen previously 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 ); } // Driver code public static void main (String[] args) { int n = 3 ; int k = 10 ; System.out.println(count_numbers(k, n, true )); } } // This code is contributed by AnkitRai01 |
Python3
# Python3 implementation of the approach # Function to return the count of # n-digit numbers that satisfy # the given conditions def count_numbers(k, n, flag) : # Base case if (n = = 1 ) : # If 0 wasn't chosen previously if (flag) : return (k - 1 ) else : return 1 # If 0 wasn't chosen previously 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 ) # Driver code n = 3 k = 10 print (count_numbers(k, n, True )) # This code is contributed by # divyamohan123 |
C#
// C# implementation of the approach using System; class GFG { // Function to return the count of // n-digit numbers that satisfy // the given conditions static int count_numbers( int k, int n, bool flag) { // Base case if (n == 1) { // If 0 wasn't chosen previously if (flag) { return (k - 1); } else { return 1; } } // If 0 wasn't chosen previously 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 ); } // Driver code public static void Main (String[] args) { int n = 3; int k = 10; Console.Write(count_numbers(k, n, true )); } } // This code is contributed by 29AjayKuma |
Javascript
<script> // Javascript implementation of the approach // Function to return the count of // n-digit numbers that satisfy // the given conditions function count_numbers(k, n, flag) { // Base case if (n == 1) { // If 0 wasn't chosen previously if (flag) { return (k - 1); } else { return 1; } } // If 0 wasn't chosen previously 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); } // Driver code let n = 3; let k = 10; document.write(count_numbers(k, n, true )); // This code is contributed by souravmahato348. </script> |
891
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++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; // Function to return the count of // n-digit numbers that satisfy // the given conditions int count_numbers( int k, int n) { // DP array to store the // pre-calculated states int dp[n + 1][2]; // Base cases dp[1][0] = 0; dp[1][1] = k - 1; for ( int i = 2; i <= n; i++) { // i-digit numbers ending with 0 // can be formed by concatenating // 0 in the end of all the (i - 1)-digit // number ending at a non-zero digit dp[i][0] = dp[i - 1][1]; // i-digit numbers ending with non-zero // can be formed by concatenating any non-zero // digit in the end of all the (i - 1)-digit // number ending with any digit dp[i][1] = (dp[i - 1][0] + dp[i - 1][1]) * (k - 1); } // n-digit number ending with // and ending with non-zero return dp[n][0] + dp[n][1]; } // Driver code int main() { int k = 10; int n = 3; cout << count_numbers(k, n); return 0; } |
Java
// Java implementation of the approach import java.util.*; class GFG { // Function to return the count of // n-digit numbers that satisfy // the given conditions static int count_numbers( int k, int n) { // DP array to store the // pre-calculated states int [][] dp = new int [n + 1 ][ 2 ]; // Base cases dp[ 1 ][ 0 ] = 0 ; dp[ 1 ][ 1 ] = k - 1 ; for ( int i = 2 ; i <= n; i++) { // i-digit numbers ending with 0 // can be formed by concatenating // 0 in the end of all the (i - 1)-digit // number ending at a non-zero digit dp[i][ 0 ] = dp[i - 1 ][ 1 ]; // i-digit numbers ending with non-zero // can be formed by concatenating any non-zero // digit in the end of all the (i - 1)-digit // number ending with any digit dp[i][ 1 ] = (dp[i - 1 ][ 0 ] + dp[i - 1 ][ 1 ]) * (k - 1 ); } // n-digit number ending with // and ending with non-zero return dp[n][ 0 ] + dp[n][ 1 ]; } // Driver code public static void main(String[] args) { int k = 10 ; int n = 3 ; System.out.println(count_numbers(k, n)); } } // This code is contributed by Rajput-Ji |
Python3
# Python3 implementation of the approach # Function to return the count of # n-digit numbers that satisfy # the given conditions def count_numbers(k, n): # DP array to store the # pre-calculated states dp = [[ 0 for i in range ( 2 )] for i in range (n + 1 )] # Base cases dp[ 1 ][ 0 ] = 0 dp[ 1 ][ 1 ] = k - 1 for i in range ( 2 , n + 1 ): # i-digit numbers ending with 0 # can be formed by concatenating # 0 in the end of all the (i - 1)-digit # number ending at a non-zero digit dp[i][ 0 ] = dp[i - 1 ][ 1 ] # i-digit numbers ending with non-zero # can be formed by concatenating any non-zero # digit in the end of all the (i - 1)-digit # number ending with any digit dp[i][ 1 ] = (dp[i - 1 ][ 0 ] + dp[i - 1 ][ 1 ]) * (k - 1 ) # n-digit number ending with # and ending with non-zero return dp[n][ 0 ] + dp[n][ 1 ] # Driver code k = 10 n = 3 print (count_numbers(k, n)) # This code is contributed by Mohit Kumar |
C#
// C# implementation of the approach using System; class GFG { // Function to return the count of // n-digit numbers that satisfy // the given conditions static int count_numbers( int k, int n) { // DP array to store the // pre-calculated states int [, ] dp = new int [n + 1, 2]; // Base cases dp[1, 0] = 0; dp[1, 1] = k - 1; for ( int i = 2; i <= n; i++) { // i-digit numbers ending with 0 // can be formed by concatenating // 0 in the end of all the (i - 1)-digit // number ending at a non-zero digit dp[i, 0] = dp[i - 1, 1]; // i-digit numbers ending with non-zero // can be formed by concatenating any non-zero // digit in the end of all the (i - 1)-digit // number ending with any digit dp[i, 1] = (dp[i - 1, 0] + dp[i - 1, 1]) * (k - 1); } // n-digit number ending with // and ending with non-zero return dp[n, 0] + dp[n, 1]; } // Driver code public static void Main(String[] args) { int k = 10; int n = 3; Console.WriteLine(count_numbers(k, n)); } } // This code is contributed by 29AjayKumar |
Javascript
<script> // Javascript implementation of the approach // Function to return the count of // n-digit numbers that satisfy // the given conditions function count_numbers(k, n) { // DP array to store the // pre-calculated states let dp = new Array(n + 1); for (let i = 0; i < n + 1; i++) dp[i] = new Array(2); // Base cases dp[1][0] = 0; dp[1][1] = k - 1; for (let i = 2; i <= n; i++) { // i-digit numbers ending with 0 // can be formed by concatenating // 0 in the end of all the (i - 1)-digit // number ending at a non-zero digit dp[i][0] = dp[i - 1][1]; // i-digit numbers ending with non-zero // can be formed by concatenating any non-zero // digit in the end of all the (i - 1)-digit // number ending with any digit dp[i][1] = (dp[i - 1][0] + dp[i - 1][1]) * (k - 1); } // n-digit number ending with // and ending with non-zero return dp[n][0] + dp[n][1]; } // Driver code let k = 10; let n = 3; document.write(count_numbers(k, n)); </script> |
891
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++
// C++ program for above approach #include <iostream> using namespace std; // Function to return the count of // n-digit numbers that satisfy // the given conditions int count_numbers( int k, int n) { // to store previous and current computations int prev_zero = 0, prev_nonzero = k - 1, curr_zero, curr_nonzero; // iterate over subproblems for ( int i = 2; i <= n; i++) { // i-digit numbers ending with 0 // can be formed by concatenating // 0 in the end of all the (i - 1)-digit // number ending at a non-zero digit curr_zero = prev_nonzero; curr_nonzero = (prev_zero + prev_nonzero) * (k - 1); // assigning values to compute further prev_zero = curr_zero; prev_nonzero = curr_nonzero; } // n-digit number ending with // and ending with non-zero return prev_zero + prev_nonzero; } // Driver Code int main() { int k = 10; int n = 3; // function call cout << count_numbers(k, n) << endl; return 0; } |
Java
public class Main { // Function to return the count of // n-digit numbers that satisfy // the given conditions public static int countNumbers( int k, int n) { // Stores the previous and current // computations int prevZero = 0 , prevNonZero = k - 1 ; int currZero, currNonZero; // iterate over subproblems for ( int i = 2 ; i <= n; i++) { // i-digit numbers ending with 0 // can be formed by concatenating // 0 in the end of all the (i - 1)-digit // number ending at a non-zero digit currZero = prevNonZero; currNonZero = (prevZero + prevNonZero) * (k - 1 ); // assigning values to // compute further prevZero = currZero; prevNonZero = currNonZero; } // n-digit number ending with // and ending with non-zero return prevZero + prevNonZero; } // Driver Code 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 : # to store previous and current computations prev_zero = 0 prev_nonzero = k - 1 curr_zero = 0 curr_nonzero = 0 # iterate over subproblems for i in range ( 2 , n + 1 ): # i-digit numbers ending with 0 # can be formed by concatenating # 0 in the end of all the (i - 1)-digit # number ending at a non-zero digit curr_zero = prev_nonzero curr_nonzero = (prev_zero + prev_nonzero) * (k - 1 ) # assigning values to compute further prev_zero = curr_zero prev_nonzero = curr_nonzero # n-digit number ending with # and ending with non-zero return prev_zero + prev_nonzero # Driver Code if __name__ = = '__main__' : k = 10 n = 3 # function call 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
// Define a function named countNumbers // that takes two arguments, k and n function countNumbers(k, n) { // Initialize variables to keep track of // the count of numbers with a zero and // non-zero starting digit let prevZero = 0, prevNonZero = k - 1; // Declare variables to store the current count // of numbers with a zero and non-zero starting digit let currZero, currNonZero; // Loop through all possible lengths of numbers up to n for (let i = 2; i <= n; i++) { // The count of numbers of length i that // start with a zero is equal to the count // of numbers of length i-1 that start with a non-zero digit currZero = prevNonZero; // The count of numbers of length i that // start with a non-zero digit is equal to // the sum of counts of numbers of length i-1 // that start with a zero or non-zero // digit multiplied by k-1 (since there are k-1 possible non-zero digits) currNonZero = (prevZero + prevNonZero) * (k - 1); // Update the previous counts of numbers with // a zero and non-zero starting digit for the next iteration prevZero = currZero; prevNonZero = currNonZero; } // Return the total count of numbers with /// a zero and non-zero starting digit return prevZero + prevNonZero; } // Set the values of k and n const k = 10; const n = 3; // Call the countNumbers function with k and n // as arguments and log the result to the console 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 ; } // Skip generating numbers with leading zeros 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 ; // consecutive digit pair of zero } return true ; } int countValidIntegers( int N, int K) { vector< int > number(N); // to store the digits of the number 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
//Java program to implement above approach import java.util.Arrays; public class GFG { // Function to check if it's valid to place the 'digit' at the specified 'index' of the number array // It returns true if it's valid and false otherwise static boolean isValid( int [] number, int index, int digit) { if (index > 0 && number[index - 1 ] == 0 && digit == 0 ) { return false ; // consecutive digit pair of zero (leading zeros) } return true ; } // Recursive function to generate all possible combinations of digits for the number static void backtrack( int [] number, int index, int N, int K, int [] count) { if (index == N) { count[ 0 ]++; // A valid number has been formed, increment the count return ; } // Skip generating numbers with leading zeros 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); } } } // Function to count the number of valid integers of length 'N' that can be formed using digits from '0' to 'K-1' static int countValidIntegers( int N, int K) { int [] number = new int [N]; // To store the digits of the number int [] count = new int [ 1 ]; // To keep track of the count // Backtrack to generate all combinations of digits and count the valid integers backtrack(number, 0 , N, K, count); return count[ 0 ]; } //Driver Code public static void main(String[] args) { int N = 3 ; // Length of the number int K = 10 ; // Base of the number system (digits from 0 to 9) int result = countValidIntegers(N, K); System.out.println(result); } } |
Python3
#Python program to implement above approach def is_valid(number, index, digit): if index > 0 and number[index - 1 ] = = 0 and digit = = 0 : return False # consecutive digit pair of zero return True def backtrack(number, index, N, K, count): if index = = N: count[ 0 ] + = 1 return # Skip generating numbers with leading zeros 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 # to store the digits of the number 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 ; // consecutive digit pair of zero } return true ; } static void Backtrack( int [] number, int index, int N, int K, ref int count) { if (index == N) { count++; return ; } // Skip generating numbers with leading zeros 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]; // to store the digits of // the number 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 to check if it's valid to place the 'digit' at the specified 'index' of the number array // It returns true if it's valid and false otherwise function isValid(number, index, digit) { if (index > 0 && number[index - 1] === 0 && digit === 0) { return false ; // consecutive digit pair of zero } return true ; } function backtrack(number, index, N, K, count) { if (index === N) { count[0]++; return ; } // Skip generating numbers with leading zeros 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); // to store the digits of the number const count = [0]; // use an array to hold the count value to pass by reference backtrack(number, 0, N, K, count); return count[0]; } const N = 3; const K = 10; const result = countValidIntegers(N, K); console.log(result); |
891
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
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!