Total numbers with no repeated digits in a range


In this article, we will discuss different approaches to calculate the number of positive integers which have no repeated digits between a given range Low to high. The first approach is a brute force approach which iterates over all the numbers in the range and check if they contain repeated digits. In our second approach, we calculated the desired count using prefix array while in our last approach we used the concept of memorization in dynamic programming to get the desired result.

Problem Statement: We are given two numbers low and high and we have to find the count of all the numbers between low to high such that the number does not contain any repeated digits.

Approach 1

This is the brute force method where we are just iterating over all the numbers from low to high and checking if they contain any repeated digits. This is the easiest approach to solving our problem.

Example

The code solution for the same is given below:

#include <bits/stdc++.h>
using namespace std;
// function that checks whether or not the number contains any repeated digits
int count(int number){
	int arr[10] = {0};
	while(number != 0) {
		int digit = number % 10;
		if(arr[digit]>=1)
		{
			return 0;
		}
		arr[digit]++;
		number = number / 10;
	}
	return 1;
}
// this function iterates over all the numbers in the range from low to high and adds the count of numbers having no repeated digits to the result
int numberofnums(int l , int h)
{
	int res = 0;
	for(int iterator = l; iterator < h + 1; ++iterator)
	{
		res = res + count(iterator);
	}

	return res ;
}
int main()
{
	int low = 1, high = 90;
	cout << "The count of numbers with no repeated digits from " << low << " to "<< high << " is "<<numberofnums(low, high);
	return 0;
}

Output

The count of numbers with no repeated digits from 1 to 90 is 82

Approach 2

This this approach, we will use a prefix array that stores the count of integers which have no repeated digits up to index “iterator”.

Steps involved in this approach are:

  • Define a function that checks if a number has repeated digits.

  • Initialize a prefix array with zeros. The prefix array will store the number of valid numbers up to a given index “iterator”.

  • Iterate from low to high for each number, check if it has repeated digits. If it does not have repeated digits, increment the prefix array at the corresponding index by 1.

  • Calculate the prefix sum of the prefix array. The prefix sum will give you the total number of valid numbers in the range.

  • Return the prefix sum.

Example

The code for this approach is given below-

#include <bits/stdc++.h>
using namespace std;
bool isvalid(int number)
{
	int arr[10] = {0};
	while(number != 0)
	{
		int digit = number % 10;
		if(arr[digit]>=1)
		{
			return false;
		}
		arr[digit]++;
		number = number / 10;
	}
	return true;
}

int count(int low, int high) {
    vector<int> prefarray(high+1, 0);
    for (int iterator = low; iterator <= high; iterator++) {
        if (isvalid(iterator)) {
            prefarray[iterator] = 1;
        }
    }
    for (int iterator = 1; iterator <= high; iterator++) {
        prefarray[iterator] += prefarray[iterator-1];
    }
    return prefarray[high] - prefarray[low-1];
}

int main() {
    int low = 21, high = 200;
    int c = count(low, high);
    cout << "The count of numbers with no repeated digits from " << low << " to "<< high << " is "<< c;
    return 0;
}

Output

The count of numbers with no repeated digits from 21 to 200 is 143

Time complexity − O(nlogn) where n is (high - low).

Space complexity − O(n)

Approach 3 Dynamic programming approach

In this approach, we will break down the problem into subproblems and will store the result of the subproblems in a memoization table

The program calculates the total number of valid numbers in a given range, i.e., numbers with no repeated digits. It uses a dynamic programming approach where the function dp(“iterator”, used) returns the number of valid numbers that can be formed starting from position “iterator” with the digits in ”used”.

We have used a memoization table to store the results of the dp function and iterate through the range of numbers to call the dp function for each number. The sum of the results of the dp function for all starting positions “iterator” is the total number of valid numbers in the range.

Example

#include <bits/stdc++.h>
using namespace std;
int dp(int iterator, set<int>& used, unordered_map<string, int>& memo, const string& high_str) {
    if ( memo.count(to_string(iterator) + "|" + to_string(used.size() ))) {
        return memo[to_string(iterator) + "|" + to_string(used.size())];
    }
    if (iterator == high_str.length())
    {
        return 1;
    }
    int count = 0;
    for (int digit = 0; digit < 10; digit++) {
        if (digit == 0 && iterator == 0) {
            continue;
        }
        if (!used.count(digit)) {
            used.insert(digit);
            count += dp(iterator+1, used, memo, high_str);
            used.erase(digit);
        }
    }
    memo[to_string(iterator) + "|" + to_string(used.size())] = count;
    return count;
}

int count_valid_numbers(int low, int high) {
    unordered_map<string, int> memo;
    string high_str = to_string(high);
    int count = 0;
    for (int num = low; num <= high; num++) {
        set<int> used;
        count += dp(0, used, memo, high_str);
    }
    return count;
}

int main() {
    int low = 21, high = 200;
    int count = count_valid_numbers(low, high);
        cout << "The count of numbers with no repeated digits from " << low   <<  " to " << high << " is "<< count;
    return 0;
}

Output

The count of numbers with no repeated digits from 21 to 200 is 116640

Conclusion − In this code we discussed three approaches to count the total numbers with no repeated digits in a range from low to high.

Updated on: 16-Aug-2023

2K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements