Open In App

Total numbers with no repeated digits in a range

Improve
Improve
Like Article
Like
Save
Share
Report

Given a range L, R                    find total such numbers in the given range such that they have no repeated digits. For example: 12 has no repeated digit. 22 has repeated digit. 102, 194 and 213 have no repeated digit. 212, 171 and 4004 have repeated digits. 

Examples: 

Input : 10 12
Output : 2
Explanation : In the given range 
10 and 12 have no repeated digit 
where as 11 has repeated digit.

Input : 1 100
Output : 90

Brute Force We will traverse through each element in the given range and count the number of digits which do not have repeated digits. 

C++

// C++ implementation of brute
// force solution.
#include <bits/stdc++.h>
using namespace std;
   
// Function to check if the given
// number has repeated digit or not
int repeated_digit(int n)
{
    unordered_set<int> s;
   
    // Traversing through each digit
    while(n != 0)
    {
        int d = n % 10;
   
        // if the digit is present
        // more than once in the
        // number
        if(s.find(d) != s.end())
        {
            // return 0 if the number
            // has repeated digit
            return 0;
        }
        s.insert(d);
        n = n / 10;
    }
    // return 1 if the number has
    // no repeated digit
    return 1;
}
   
// Function to find total number
// in the given range which has
// no repeated digit
int calculate(int L,int R)
{
    int answer = 0;
   
    // Traversing through the range
    for(int i = L; i < R + 1; ++i)
    {
   
        // Add 1 to the answer if i has
        // no repeated digit else 0
        answer = answer + repeated_digit(i);
    }
   
    return answer ;
}
   
// Driver Code
int main()
{
    int L = 1, R = 100;
   
    // Calling the calculate
    cout << calculate(L, R);
    return 0;
}
   
// This code is contributed by
// Sanjit_Prasad

                    

Java

// Java implementation of brute
// force solution.
import java.util.LinkedHashSet;
 
class GFG
{
// Function to check if the given
// number has repeated digit or not
static int repeated_digit(int n)
{
    LinkedHashSet<Integer> s = new LinkedHashSet<>();
 
    // Traversing through each digit
    while (n != 0)
    {
        int d = n % 10;
 
        // if the digit is present
        // more than once in the
        // number
        if (s.contains(d))
        {
            // return 0 if the number
            // has repeated digit
            return 0;
        }
        s.add(d);
        n = n / 10;
    }
     
    // return 1 if the number has
    // no repeated digit
    return 1;
}
 
// Function to find total number
// in the given range which has
// no repeated digit
static int calculate(int L, int R)
{
    int answer = 0;
 
    // Traversing through the range
    for (int i = L; i < R + 1; ++i)
    {
 
        // Add 1 to the answer if i has
        // no repeated digit else 0
        answer = answer + repeated_digit(i);
    }
 
    return answer;
}
 
// Driver Code
public static void main(String[] args)
{
    int L = 1, R = 100;
     
    // Calling the calculate
    System.out.println(calculate(L, R));
}
}
 
// This code is contributed by RAJPUT-JI

                    

Python3

# Python implementation of brute
# force solution.
 
# Function to check if the given
# number has repeated digit or not
def repeated_digit(n):
    a = []
     
    # Traversing through each digit
    while n != 0:
        d = n%10
         
        # if the digit is present
        # more than once in the
        # number
        if d in a:
             
            # return 0 if the number
            # has repeated digit
            return 0
        a.append(d)
        n = n//10
     
    # return 1 if the number has no
    # repeated digit
    return 1
 
# Function to find total number
# in the given range which has
# no repeated digit
def calculate(L,R):
    answer = 0
     
    # Traversing through the range
    for i in range(L,R+1):
         
        # Add 1 to the answer if i has
        # no repeated digit else 0
        answer = answer + repeated_digit(i)
     
    # return answer
    return answer
     
# Driver's Code
L=1
R=100
 
# Calling the calculate
print(calculate(L, R))

                    

C#

// C# implementation of brute
// force solution.
using System;
using System.Collections.Generic;
 
class GFG
{
 
// Function to check if the given
// number has repeated digit or not
static int repeated_digit(int n)
{
    var s = new HashSet<int>();
 
    // Traversing through each digit
    while (n != 0)
    {
        int d = n % 10;
 
        // if the digit is present
        // more than once in the
        // number
        if (s.Contains(d))
        {
            // return 0 if the number
            // has repeated digit
            return 0;
        }
        s.Add(d);
        n = n / 10;
    }
     
    // return 1 if the number has
    // no repeated digit
    return 1;
}
 
// Function to find total number
// in the given range which has
// no repeated digit
static int calculate(int L, int R)
{
    int answer = 0;
 
    // Traversing through the range
    for (int i = L; i < R + 1; ++i)
    {
 
        // Add 1 to the answer if i has
        // no repeated digit else 0
        answer = answer + repeated_digit(i);
    }
 
    return answer;
}
 
// Driver Code
public static void Main(String[] args)
{
    int L = 1, R = 100;
     
    // Calling the calculate
    Console.WriteLine(calculate(L, R));
}
}
 
// This code is contributed by RAJPUT-JI

                    

PHP

<?php
// PHP implementation of
// brute force solution.
 
// Function to check if
// the given number has
// repeated digit or not
function repeated_digit($n)
{
    $c = 10;
    $a = array_fill(0, $c, 0);
     
    // Traversing through
    // each digit
    while($n > 0)
    {
        $d = $n % 10;
         
        // if the digit is present
        // more than once in the
        // number
        if ($a[$d] > 0)
        {
            // return 0 if the number
            // has repeated digit
            return 0;
        }
        $a[$d]++;
        $n = (int)($n / 10);
    }
     
    // return 1 if the number
    // has no repeated digit
    return 1;
}
 
// Function to find total
// number in the given range
// which has no repeated digit
function calculate($L, $R)
{
    $answer = 0;
     
    // Traversing through
    // the range
    for($i = $L; $i <= $R; $i++)
    {
         
        // Add 1 to the answer if
        // i has no repeated digit
        // else 0
        $answer += repeated_digit($i);
    }
     
    // return answer
    return $answer;
}
 
// Driver Code
$L = 1;
$R = 100;
 
// Calling the calculate
echo calculate($L, $R);
 
// This code is contributed by mits
?>

                    

Javascript

// JS implementation of brute
// force solution.
 
// Function to check if the given
// number has repeated digit or not
function repeated_digit(n)
{
    let s = new Set();
 
    // Traversing through each digit
    while(n != 0)
    {
        let d = n % 10;
 
        // if the digit is present
        // more than once in the
        // number
        if(s.has(d))
        {
            // return 0 if the number
            // has repeated digit
            return 0;
        }
        s.add(d);
        n = Math.floor(n / 10);
    }
    // return 1 if the number has
    // no repeated digit
    return 1;
}
 
// Function to find total number
// in the given range which has
// no repeated digit
function calculate(L, R)
{
    let answer = 0;
 
    // Traversing through the range
    for(var i = L; i < R + 1; ++i)
    {
 
        // Add 1 to the answer if i has
        // no repeated digit else 0
        answer = answer + repeated_digit(i);
    }
 
    return answer ;
}
 
// Driver Code
let  L = 1, R = 100;
 
// Calling the calculate
console.log(calculate(L, R))
 
 
// This code is contributed by
// phasing17

                    

Output
90

This method will answer each query in O( N ) time. 

Auxiliary Space: O(log(N))

Efficient Approach

We will calculate a prefix array of the numbers which have no repeated digit. Prefix[i]                    = Total number with no repeated digit less than or equal to 1. Therefore each query can be solved in O(1) time. Answer = Prefix[R] - Prefix[L-1]

Below is the implementation of above idea.

C++

// C++ implementation of above idea
#include <bits/stdc++.h>
 
using namespace std;
 
// Maximum
int MAX = 1000;
 
// Prefix Array
vector<int> Prefix = {0};
 
// Function to check if the given
// number has repeated digit or not
int repeated_digit(int n)
{
     
    unordered_set<int> a;
    int d;
     
    // Traversing through each digit
    while (n != 0)
    {
        d = n % 10;
         
        // if the digit is present
        // more than once in the
        // number
        if (a.find(d) != a.end())
             
            // return 0 if the number
            // has repeated digit
            return 0;
         
        a.insert(d);
        n = n / 10;
    }
     
    // return 1 if the number has no
    // repeated digit
    return 1;
}
 
// Function to pre calculate
// the Prefix array
void pre_calculation(int MAX)
{
     
    Prefix.push_back(repeated_digit(1));
     
    // Traversing through the numbers
    // from 2 to MAX
    for (int i = 2; i < MAX + 1; i++)
         
        // Generating the Prefix array
        Prefix.push_back(repeated_digit(i) + Prefix[i-1]);
}
 
// Calculate Function
int calculate(int L,int R)
{
     
    // Answer
    return Prefix[R] - Prefix[L-1];
}
 
// Driver code
int main()
{
    int L = 1, R = 100;
     
    // Pre-calculating the Prefix array.
    pre_calculation(MAX);
     
    // Calling the calculate function
    // to find the total number of number
    // which has no repeated digit
    cout << calculate(L, R) << endl;
 
    return 0;
}
 
// This code is contributed by Rituraj Jain

                    

Java

// Java implementation of above idea
import java.util.*;
 
class GFG
{
 
    // Maximum
    static int MAX = 100;
 
    // Prefix Array
    static Vector<Integer> Prefix = new Vector<>();
 
    // Function to check if the given
    // number has repeated digit or not
    static int repeated_digit(int n)
    {
        HashSet<Integer> a = new HashSet<>();
        int d;
 
        // Traversing through each digit
        while (n != 0)
        {
            d = n % 10;
 
            // if the digit is present
            // more than once in the
            // number
            if (a.contains(d))
 
                // return 0 if the number
                // has repeated digit
                return 0;
            a.add(d);
            n /= 10;
        }
 
        // return 1 if the number has no
        // repeated digit
        return 1;
    }
 
    // Function to pre calculate
    // the Prefix array
    static void pre_calculations()
    {
        Prefix.add(0);
        Prefix.add(repeated_digit(1));
 
        // Traversing through the numbers
        // from 2 to MAX
        for (int i = 2; i < MAX + 1; i++)
 
            // Generating the Prefix array
            Prefix.add(repeated_digit(i) + Prefix.elementAt(i - 1));
    }
 
    // Calculate Function
    static int calculate(int L, int R)
    {
 
        // Answer
        return Prefix.elementAt(R) - Prefix.elementAt(L - 1);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int L = 1, R = 100;
 
        // Pre-calculating the Prefix array.
        pre_calculations();
 
        // Calling the calculate function
        // to find the total number of number
        // which has no repeated digit
        System.out.println(calculate(L, R));
    }
}
 
// This code is contributed by
// sanjeev2552

                    

Python3

# Python implementation of
# above idea
 
# Prefix Array
Prefix = [0]
 
# Function to check if
# the given number has
# repeated digit or not
def repeated_digit(n):
    a = []
     
    # Traversing through each digit
    while n != 0:
        d = n%10
         
        # if the digit is present
        # more than once in the
        # number
        if d in a:
             
            # return 0 if the number
            # has repeated digit
            return 0
        a.append(d)
        n = n//10
     
    # return 1 if the number has no
    # repeated digit
    return 1
 
# Function to pre calculate
# the Prefix array
def pre_calculation(MAX):
     
    # To use to global Prefix array
    global Prefix
    Prefix.append(repeated_digit(1))
     
    # Traversing through the numbers
    # from 2 to MAX
    for i in range(2,MAX+1):
         
        # Generating the Prefix array
        Prefix.append( repeated_digit(i) +
                       Prefix[i-1] )
 
# Calculate Function
def calculate(L,R):
     
    # Answer
    return Prefix[R]-Prefix[L-1]
 
 
# Driver Code
 
# Maximum
MAX = 1000
 
# Pre-calculating the Prefix array.
pre_calculation(MAX)
 
# Range
L=1
R=100
 
# Calling the calculate function
# to find the total number of number
# which has no repeated digit
print(calculate(L, R))

                    

C#

// C# implementation of above idea
using System;
using System.Collections.Generic;
 
class GFG
{
 
    // Maximum
    static int MAX = 100;
 
    // Prefix Array
    static List<int> Prefix = new List<int>();
 
    // Function to check if the given
    // number has repeated digit or not
    static int repeated_digit(int n)
    {
        HashSet<int> a = new HashSet<int>();
        int d;
 
        // Traversing through each digit
        while (n != 0)
        {
            d = n % 10;
 
            // if the digit is present
            // more than once in the
            // number
            if (a.Contains(d))
 
                // return 0 if the number
                // has repeated digit
                return 0;
            a.Add(d);
            n /= 10;
        }
 
        // return 1 if the number has no
        // repeated digit
        return 1;
    }
 
    // Function to pre calculate
    // the Prefix array
    static void pre_calculations()
    {
        Prefix.Add(0);
        Prefix.Add(repeated_digit(1));
 
        // Traversing through the numbers
        // from 2 to MAX
        for (int i = 2; i < MAX + 1; i++)
 
            // Generating the Prefix array
            Prefix.Add(repeated_digit(i) +
                           Prefix[i - 1]);
    }
 
    // Calculate Function
    static int calculate(int L, int R)
    {
 
        // Answer
        return Prefix[R] - Prefix[L - 1];
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        int L = 1, R = 100;
 
        // Pre-calculating the Prefix array.
        pre_calculations();
 
        // Calling the calculate function
        // to find the total number of number
        // which has no repeated digit
        Console.WriteLine(calculate(L, R));
    }
}
 
// This code is contributed by 29AjayKumar

                    

JavaScript

<script>
    // JavaScript implementation of brute
// force solution.
 
// Function to check if the given
// number has repeated digit or not
function repeated_digit(n){
    const s = new Set();
 
    // Traversing through each digit
    while(n != 0){
        let d = n % 10;
 
        // if the digit is present
        // more than once in the
        // number
        if(s.has(d)){
            // return 0 if the number
            // has repeated digit
            return 0;
        }
        s.add(d);
        n = Math.floor(n / 10);
    }
    // return 1 if the number has
    // no repeated digit
    return 1;
}
 
// Function to find total number
// in the given range which has
// no repeated digit
function calculate(L, R){
    let answer = 0;
 
    // Traversing through the range
    for(let i = L; i < R + 1; ++i){
        // Add 1 to the answer if i has
        // no repeated digit else 0
        answer = answer + repeated_digit(i);
    }
 
    return answer ;
}
 
// Driver Code
{
    let L = 1, R = 100;
 
    // Calling the calculate
    console.log(calculate(L, R));
}
 
// This code is contributed by Gautam goel (gautamgoel962)
</script>

                    

Output
90

Efficient Approach:  The above approach can be optimized based on the following idea:

Dynamic programming can be used to solve this problem

  • dp[i][j][k][l] represents numbers in the range with i’th position to be filled, j represents tight condition, k represents bitmask set for each digit from 0 to 9 and l represents whether previously non zero digit number taken or not. 
     
  • It can be observed that the recursive function is called exponential times. That means that some states are called repeatedly. 
    So the idea is to store the value of each state. This can be done using by store the value of a state and whenever the function is called, return the stored value without computing again.
     
  • First answer will be calculated for 0 to A – 1 and then calculated for 0 to B then latter one is subtracted with prior one to get answer for range [L, R]

Follow the steps below to solve the problem:

  • Create a recursive function that takes four parameters i representing the position to be filled, j representing the tight condition, k representing bitmask and l representing whether previously non zero digit taken or not.
  • Call the recursive function for choosing all digits from 0 to 9 apart from N.
  • Base case if N size digit formed return 1;
  • Create a 2d array dp[N][2][M][2] initially filled with -1.
  • If the answer for a particular state is computed then save it in dp[i][j][k][l].
  • If the answer for a particular state is already computed then just return dp[i][j][k][l].

Below is the implementation of the above approach:

C++

// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// DP table initialized with -1
int dp[11][2][(1LL << 10) - 1][2];
 
// Recursive Function to find numbers
// in the range L to R such that its
// digits are distinct
int recur(int i, int j, int k, int l, string a)
{
    // Base case
    if (i == a.size()) {
        return 1;
    }
 
    // If answer for current state is already
    // calculated then just return dp[i][j][k]
    if (dp[i][j][k][l] != -1)
        return dp[i][j][k][l];
 
    // Answer initialized with zero
    int ans = 0;
 
    // Tight condition true
    if (j == 1) {
 
        // Iterating from 0 to max value of
        // tight condition
        for (int digit = 0; digit <= 9; digit++) {
 
            // mask for digit
            int mask = (1 << digit);
 
            // if that digit is available to use
            if (mask & k) {
 
                // calling recursive function for max digit
                // taken and retaining tight condition
                if (digit == ((int)a[i] - 48)) {
                    ans += recur(i + 1, 1, k - (1 << digit),
                                 1, a);
                }
 
                // calling recursive function for zero
                // and dropping tight condition
                else if (digit == 0) {
                    ans += recur(i + 1, 0, k, 0, a);
                }
 
                // calling recursive function for number
                // less than max and dropping condition
                else if (digit < ((int)a[i] - 48)) {
                    ans += recur(i + 1, 0, k - (1 << digit),
                                 1, a);
                }
            }
        }
    }
 
    // Tight condition false
    else {
 
        // Iterating for all digits
        for (int digit = 0; digit <= 9; digit++) {
            int mask = (1 << digit);
 
            if (mask & k) {
                // calling recursive function for
                // not taking anything
                if (digit == 0 and l == 0)
                    ans += recur(i + 1, 0, k, 0, a);
 
                // calling recursive function for
                // taking zero
                else if (digit == 0 and l == 1)
                    ans += recur(i + 1, 0, k - (1 << digit),
                                 1, a);
 
                // calling recursive function for taking
                // digits from 1 to 9
                else
                    ans += recur(i + 1, 0, k - (1 << digit),
                                 1, a);
            }
        }
    }
 
    // Save and return dp value
    return dp[i][j][k][l] = ans;
}
 
// Function to find numbers
// in the range L to R such that its
// digits are distinct
int countInRange(int A, int B)
{
 
    // Initializing dp array with - 1
    memset(dp, -1, sizeof(dp));
 
    A--;
    string L = to_string(A), R = to_string(B);
 
    // Numbers with distinct digits in range 0 to L
    int ans1 = recur(0, 1, (1 << 10) - 1, 0, L);
 
    // Initializing dp array with - 1
    memset(dp, -1, sizeof(dp));
 
    // Numbers with distinct digits in range 0 to R
    int ans2 = recur(0, 1, (1 << 10) - 1, 0, R);
 
    // Difference of ans2 and ans1
    // will generate answer for required range
    return ans2 - ans1;
}
 
// Driver Code
int main()
{
    // Input 1
    int L = 1, R = 100;
 
    // Function Call
    cout << countInRange(L, R) << endl;
    return 0;
}

                    

Java

// Java code to implement the approach
import java.util.*;
 
class GFG {
 
  // DP table initialized with -1
  static int[][][][] dp = new int[11][2][(1 << 10)][2];
 
  // Recursive Function to find numbers
  // in the range L to R such that its
  // digits are distinct
  static int recur(int i, int j, int k, int l, String a)
  {
    // Base case
    if (i == a.length()) {
      return 1;
    }
 
    // If answer for current state is already
    // calculated then just return dp[i][j][k]
    if (dp[i][j][k][l] != -1)
      return dp[i][j][k][l];
 
    // Answer initialized with zero
    int ans = 0;
 
    // Tight condition true
    if (j == 1) {
      // Iterating from 0 to max value of
      // tight condition
      for (int digit = 0; digit <= 9; digit++) {
        // mask for digit
        int mask = (1 << digit);
 
        // if that digit is available to use
        if ((mask & k) != 0) {
 
          // calling recursive function for max
          // digit taken and retaining tight
          // condition
          if (digit == ((int)a.charAt(i) - 48)) {
            ans += recur(i + 1, 1,
                         k - (1 << digit), 1,
                         a);
          }
 
          // calling recursive function for zero
          // and dropping tight condition
          else if (digit == 0) {
            ans += recur(i + 1, 0, k, 0, a);
          }
 
          // calling recursive function for number
          // less than max and dropping condition
          else if (digit
                   < ((int)a.charAt(i) - 48)) {
            ans += recur(i + 1, 0,
                         k - (1 << digit), 1,
                         a);
          }
        }
      }
    }
    // Tight condition false
    else {
      // Iterating for all digits
      for (int digit = 0; digit <= 9; digit++) {
        int mask = (1 << digit);
 
        if ((mask & k) != 0) {
          // calling recursive function for
          // not taking anything
          if (digit == 0 && l == 0)
            ans += recur(i + 1, 0, k, 0, a);
 
          // calling recursive function for
          // taking zero
          else if (digit == 0 && l == 1)
            ans += recur(i + 1, 0,
                         k - (1 << digit), 1,
                         a);
 
          // calling recursive function for taking
          // digits from 1 to 9
          else
            ans += recur(i + 1, 0,
                         k - (1 << digit), 1,
                         a);
        }
      }
    }
 
    // Save and return dp value
    return dp[i][j][k][l] = ans;
  }
 
  // Function to find numbers
  // in the range L to R such that its
  // digits are distinct
  static int countInRange(int A, int B)
  {
 
    // Initializing dp array with - 1
    for (int[][][] table : dp) {
      for (int[][] row : table) {
        for (int[] innerRow : row) {
          Arrays.fill(innerRow, -1);
        }
      }
    }
 
    A--;
    String L = String.valueOf(A);
    String R = String.valueOf(B);
 
    // Numbers with distinct digits in range 0 to L
    int ans1 = recur(0, 1, (1 << 10) - 1, 0, L);
 
    // Initializing dp array with - 1
    for (int[][][] table : dp) {
      for (int[][] row : table) {
        for (int[] innerRow : row) {
          Arrays.fill(innerRow, -1);
        }
      }
    }
 
    // Numbers with distinct digits in range 0 to R
    int ans2 = recur(0, 1, (1 << 10) - 1, 0, R);
 
    // Difference of ans2 and ans1
    // will generate answer for required range
    return ans2 - ans1;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    // Input 1
    int L = 1, R = 100;
 
    // Function Call
    System.out.println(countInRange(L, R));
  }
}

                    

Python3

# Python code to implement the approach
# DP table initialized with -1
dp = [[[[-1 for l in range(2)] for k in range(1 << 10)] for j in range(2)] for i in range(11)]
 
def memset(dp):
    for i in range(11):
        for j in range(2):
            for k in range(1 << 10):
                for l in range(2):
                    dp[i][j][k][l] = -1
 
# Recursive Function to find numbers
# in the range L to R such that its
# digits are distinct
def recur(i, j, k, l, a):
    # Base case
    if i == len(a):
        return 1
     
    # If answer for current state is already
    # calculated then just return dp[i][j][k]
    if dp[i][j][k][l] != -1:
        return dp[i][j][k][l]
     
    # Answer initialized with zero
    ans = 0
     
    # Tight condition true
    if j == 1:
       
        # Iterating from 0 to max value of
        # tight condition
        for digit in range(10):
           
            # mask for digit
            mask = (1 << digit)
             
            # if that digit is available to use
            if mask & k:
               
                # calling recursive function for max digit
                # taken and retaining tight condition
                if digit == int(a[i]):
                    ans += recur(i + 1, 1, k - (1 << digit), 1, a)
                     
                # calling recursive function for zero
                # and dropping tight condition
                elif digit == 0:
                    ans += recur(i + 1, 0, k, 0, a)
                     
                # calling recursive function for number
                # less than max and dropping condition
                elif digit < int(a[i]):
                    ans += recur(i + 1, 0, k - (1 << digit), 1, a)
                     
    # Tight condition false
    else:
       
        # Iterating for all digits
        for digit in range(10):
            mask = (1 << digit)
            if mask & k:
               
                # calling recursive function for
                # not taking anything
                if digit == 0 and l == 0:
                    ans += recur(i + 1, 0, k, 0, a)
                     
                # calling recursive function for
                # taking zero
                elif digit == 0 and l == 1:
                    ans += recur(i + 1, 0, k - (1 << digit), 1, a)
                     
                # calling recursive function for taking
                # digits from 1 to 9
                else:
                    ans += recur(i + 1, 0, k - (1 << digit), 1, a)
 
    dp[i][j][k][l] = ans
     
    # Save and return dp value
    return ans
 
# Function to find numbers
# in the range L to R such that its
# digits are distinct
def countInRange(A, B):
   
    # Initializing dp array with - 1
    memset(dp)
    A -= 1
    L = str(A)
    R = str(B)
     
    # Numbers with distinct digits in range 0 to
    ans1 = recur(0, 1, (1 << 10) - 1, 0, L)
     
    # Initializing dp array with - 1
    memset(dp)
     
    # Numbers with distinct digits in range 0 to R
    ans2 = recur(0, 1, (1 << 10) - 1, 0, R)
     
    # Difference of ans2 and ans1
    # will generate answer for required range
    return ans2 - ans1
 
# Driver Code
 
# Input 1
L = 1
R = 100
 
# Function Call
print(countInRange(L, R))
 
# This code is contributed by prajwalkandekar123.

                    

C#

// C# code to implement the approach
using System;
public class GFG
{
    // DP table initialized with -1
    static int[,,,] dp = new int[11, 2, (1 << 10), 2];
 
    // Recursive Function to find numbers
    // in the range L to R such that its
    // digits are distinct
    static int recur(int i, int j, int k, int l, String a)
    {
        // Base case
        if (i == a.Length)
        {
            return 1;
        }
 
        // If answer for current state is already
        // calculated then just return dp[i][j][k]
        if (dp[i, j, k, l] != -1)
            return dp[i, j, k, l];
 
        // Answer initialized with zero
        int ans = 0;
 
        // Tight condition true
        if (j == 1)
        {
            // Iterating from 0 to max value of
            // tight condition
            for (int digit = 0; digit <= 9; digit++)
            {
                // mask for digit
                int mask = (1 << digit);
 
                // if that digit is available to use
                if ((mask & k) != 0)
                {
 
                    // calling recursive function for max
                    // digit taken and retaining tight
                    // condition
                    if (digit == ((int)a[i] - 48))
                    {
                        ans += recur(i + 1, 1,
                                     k - (1 << digit), 1,
                                     a);
                    }
 
                    // calling recursive function for zero
                    // and dropping tight condition
                    else if (digit == 0)
                    {
                        ans += recur(i + 1, 0, k, 0, a);
                    }
 
                    // calling recursive function for number
                    // less than max and dropping condition
                    else if (digit
                             < ((int)a[i] - 48))
                    {
                        ans += recur(i + 1, 0,
                                     k - (1 << digit), 1,
                                     a);
                    }
                }
            }
        }
        // Tight condition false
        else
        {
            // Iterating for all digits
            for (int digit = 0; digit <= 9; digit++)
            {
                int mask = (1 << digit);
 
                if ((mask & k) != 0)
                {
                    // calling recursive function for
                    // not taking anything
                    if (digit == 0 && l == 0)
                        ans += recur(i + 1, 0, k, 0, a);
 
                    // calling recursive function for
                    // taking zero
                    else if (digit == 0 && l == 1)
                        ans += recur(i + 1, 0,
                                     k - (1 << digit), 1,
                                     a);
 
                    // calling recursive function for taking
                    // digits from 1 to 9
                    else
                        ans += recur(i + 1, 0,
                                     k - (1 << digit), 1,
                                     a);
                }
            }
        }
 
        // Save and return dp value
        return dp[i, j, k, l] = ans;
    }
 
    // Function to find numbers
    // in the range L to R such that its
    // digits are distinct
    static int countInRange(int A, int B)
    {
 
        // Initializing dp array with - 1
        for (int i = 0; i < dp.GetLength(0); i++)
        {
            for (int j = 0; j < dp.GetLength(1); j++)
            {
                for (int k = 0; k < dp.GetLength(2); k++)
                {
                    for (int l = 0; l < dp.GetLength(3); l++)
                    {
                        dp[i, j, k, l] = -1;
                    }
                }
            }
        }
 
        A--;
        String L = A.ToString();
        String R = B.ToString();
 
        // Numbers with distinct digits in range 0 to L
        int ans1 = recur(0, 1, (1 << 10) - 1, 0, L);
 
        // Initializing dp array with - 1
        for (int i = 0; i < dp.GetLength(0); i++)
        {
            for (int j = 0; j < dp.GetLength(1); j++)
            {
                for (int k = 0; k < dp.GetLength(2); k++)
                {
                    for (int l = 0; l < dp.GetLength(3); l++)
                    {
                        dp[i, j, k, l] = -1;
                    }
                }
            }
        }
 
        // Numbers with distinct digits in range 0 to R
        int ans2 = recur(0, 1, (1 << 10) - 1, 0, R);
 
        // Difference of ans2 and ans1
        // will generate answer for required range
        return ans2 - ans1;
    }
 
    // Driver Code
    public static void Main(String[] args)
    {
        // Input 1
        int L = 1, R = 100;
 
        // Function Call
        Console.WriteLine(countInRange(L, R));
    }
}

                    

Javascript

// Javascript code to implement the approach
 
// DP table initialized with -1
//int dp[11][2][(1LL << 10) - 1][2];
let dp=new Array(11);
for(let i=0; i<11; i++)
{
    dp[i]=new Array(2);
    for(let j=0; j<2; j++)
    {
        dp[i][j]=new Array(1<<10);
        for(let k=0; k<(1<<10); k++)
            dp[i][j][k]=new Array(2);
    }
}
 
function memset(dp)
{
    for(let i=0; i<11; i++)
    {
        for(let j=0; j<2; j++)
        {
            for(let k=0; k<(1<<10); k++)
                for(let l=0; l<2; l++)
                    dp[i][j][k][l]=-1;
        }
    }
}
 
// Recursive Function to find numbers
// in the range L to R such that its
// digits are distinct
function recur(i, j, k, l, a)
{
    // Base case
    if (i == a.length) {
        return 1;
    }
 
    // If answer for current state is already
    // calculated then just return dp[i][j][k]
    if (dp[i][j][k][l] != -1)
        return dp[i][j][k][l];
 
    // Answer initialized with zero
    let ans = 0;
 
    // Tight condition true
    if (j == 1) {
 
        // Iterating from 0 to max value of
        // tight condition
        for (let digit = 0; digit <= 9; digit++) {
 
            // mask for digit
            let mask = (1 << digit);
 
            // if that digit is available to use
            if (mask & k) {
 
                // calling recursive function for max digit
                // taken and retaining tight condition
                if (digit == (parseInt(a[i]))) {
                    ans += recur(i + 1, 1, k - (1 << digit),
                                 1, a);
                }
 
                // calling recursive function for zero
                // and dropping tight condition
                else if (digit == 0) {
                    ans += recur(i + 1, 0, k, 0, a);
                }
 
                // calling recursive function for number
                // less than max and dropping condition
                else if (digit < (parseInt(a[i]))) {
                    ans += recur(i + 1, 0, k - (1 << digit),
                                 1, a);
                }
            }
        }
    }
 
    // Tight condition false
    else {
 
        // Iterating for all digits
        for (let digit = 0; digit <= 9; digit++) {
            let mask = (1 << digit);
 
            if (mask & k) {
                // calling recursive function for
                // not taking anything
                if (digit == 0 && l == 0)
                    ans += recur(i + 1, 0, k, 0, a);
 
                // calling recursive function for
                // taking zero
                else if (digit == 0 && l == 1)
                    ans += recur(i + 1, 0, k - (1 << digit),
                                 1, a);
 
                // calling recursive function for taking
                // digits from 1 to 9
                else
                    ans += recur(i + 1, 0, k - (1 << digit),
                                 1, a);
            }
        }
    }
 
    // Save and return dp value
    return dp[i][j][k][l] = ans;
}
 
// Function to find numbers
// in the range L to R such that its
// digits are distinct
function countInRange(A, B)
{
 
    // Initializing dp array with - 1
    memset(dp);
 
    A--;
    let L = A.toString(), R = B.toString();
 
    // Numbers with distinct digits in range 0 to L
    let ans1 = recur(0, 1, (1 << 10) - 1, 0, L);
 
    // Initializing dp array with - 1
    memset(dp);
 
    // Numbers with distinct digits in range 0 to R
    let ans2 = recur(0, 1, (1 << 10) - 1, 0, R);
 
    // Difference of ans2 and ans1
    // will generate answer for required range
    return ans2 - ans1;
}
 
// Driver Code
    // Input 1
    let L = 1, R = 100;
 
    // Function Call
    console.log(countInRange(L, R));

                    

Output
90

Time Complexity: O(log(R – L) * M) 
Auxiliary Space: O(log(R – L) * M)

Where M is the all possible subsets of set containing all digits from 0 to 9 for bitmask M = 1024  

Related Articles:



Last Updated : 08 May, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads