Open In App

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

Last Updated : 05 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads