Thursday, January 9, 2025
Google search engine
HomeData Modelling & AICount of N-digit numbers in base K with no two consecutive zeroes

Count of N-digit numbers in base K with no two consecutive zeroes

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: 
 

  1. The integers must be of exactly N digits.
  2. There should be no leading 0.
  3. 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>


Output

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>


Output

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] * # 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);


Output

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

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments