Count of subarrays of an Array having all unique digits

Given an array A containing N positive integers, the task is to find the number of subarrays of this array such that in each subarray, no digit is repeated twice, i.e. all the digits of the subarray must be unique.

Examples:

Input: A = [1, 12, 23, 34]
Output: 7
The subarrays are: {1}, {12}, {23}, {34}, {1, 23}, {1, 34}, {12, 34}
Therefore the count of such subarrays = 7



Input: A = [5, 12, 2, 1, 165, 2323, 7]
Output: 33

Naive approach: Generate all subarrays of the array and traverse through them to check whether the given condition is satisfied or not. Print the count of such subarray at the end.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to find the count
// of subarrays of an Array
// having all unique digits
  
#include <bits/stdc++.h>
using namespace std;
  
// Function to check whether
// the subarray has all unique digits
bool check(vector<int>& v)
{
  
    // Storing all digits occurred
    set<int> digits;
  
    // Traversing all the numbers of v
    for (int i = 0; i < v.size(); i++) {
        // Storing all digits of v[i]
        set<int> d;
  
        while (v[i]) {
            d.insert(v[i] % 10);
            v[i] /= 10;
        }
  
        // Checking whether digits of v[i]
        // have already occurred
        for (auto it : d) {
            if (digits.count(it))
                return false;
        }
  
        // Inserting digits of v[i] in the set
        for (auto it : d)
            digits.insert(it);
    }
  
    return true;
}
  
// Function to count the number
// subarray with all digits unique
int numberOfSubarrays(int a[], int n)
{
  
    int answer = 0;
  
    // Traverse through all the subarrays
    for (int i = 1; i < (1 << n); i++) {
        // To store elements of this subarray
        vector<int> temp;
  
        // Generate all subarray
        // and store it in vector
        for (int j = 0; j < n; j++) {
            if (i & (1 << j))
                temp.push_back(a[j]);
        }
  
        // Check whether this subarray
        // has all digits unique
        if (check(temp))
  
            // Increase the count
            answer++;
    }
  
    // Return the count
    return answer;
}
  
// Driver code
int main()
{
    int N = 4;
    int A[] = { 1, 12, 23, 34 };
  
    cout << numberOfSubarrays(A, N);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to find the count
// of subarrays of an Array
// having all unique digits
   
  
import java.util.*;
  
class GFG{
   
// Function to check whether
// the subarray has all unique digits
static boolean check(Vector<Integer> v)
{
   
    // Storing all digits occurred
    HashSet<Integer> digits = new HashSet<Integer>();
   
    // Traversing all the numbers of v
    for (int i = 0; i < v.size(); i++) {
        // Storing all digits of v[i]
        HashSet<Integer> d = new HashSet<Integer>();
   
        while (v.get(i)>0) {
            d.add(v.get(i) % 10);
            v.set(i, v.get(i)/10);
        }
   
        // Checking whether digits of v[i]
        // have already occurred
        for (int it : d) {
            if (digits.contains(it))
                return false;
        }
   
        // Inserting digits of v[i] in the set
        for (int it : d)
            digits.add(it);
    }
   
    return true;
}
   
// Function to count the number
// subarray with all digits unique
static int numberOfSubarrays(int a[], int n)
{
   
    int answer = 0;
   
    // Traverse through all the subarrays
    for (int i = 1; i < (1 << n); i++) {
        // To store elements of this subarray
        Vector<Integer> temp = new Vector<Integer>();
   
        // Generate all subarray
        // and store it in vector
        for (int j = 0; j < n; j++) {
            if ((i & (1 << j))>0)
                temp.add(a[j]);
        }
   
        // Check whether this subarray
        // has all digits unique
        if (check(temp))
   
            // Increase the count
            answer++;
    }
   
    // Return the count
    return answer;
}
   
// Driver code
public static void main(String[] args)
{
    int N = 4;
    int A[] = { 1, 12, 23, 34 };
   
    System.out.print(numberOfSubarrays(A, N));
}
}
  
// This code is contributed by 29AjayKumar

chevron_right


Output:

7

Time Complexity: O(N * 2N)

Efficient Approach: This approach depends upon the fact that there exist only 10 unique digits in the Decimal number system. Therefore the longest subarray will have only 10 digits in it, to meet the required condition.

  • We will use Bitmasking and Dynamic Programming to solve the problem.
  • Since there are only 10 digits, consider a 10-bit representation of every number where each bit is 1 if digit corresponding to that bit is present in that number.
  • Let, i be the current array element (elements from 1 to i-1 are already processed). An integer variable ‘mask‘ indicates the digits which have already occurred in the subarray. If i’th bit is set in the mask, then i’th digit has occurred, else not.
  • At each step of recurrence relation, the element can either be included in the subarray or not. If the element is not included in the subarray, then simply move to the next index. If it is included, change the mask by setting all the bits corresponding to the current element’s digit, ON in the mask.

    Note: The current element can only be included if all of its digits have not occurred previously.

  • This condition will be satisfied only if the bits corresponding to the current element’s digits in the mask are OFF.
  • If we draw the complete recursion tree, we can observe that many subproblems are being solved again and again. So we use Dynamic Programming. A table dp[][] is used such that for every index dp[i][j], i is the position of the element in the array and j is the mask.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to find the count
// of subarrays of an Array
// having all unique digits
  
#include <bits/stdc++.h>
using namespace std;
  
// Dynamic programming table
int dp[5000][(1 << 10) + 5];
  
// Function to obtain
// the mask for any integer
int getmask(int val)
{
    int mask = 0;
  
    if (val == 0)
        return 1;
  
    while (val) {
        int d = val % 10;
        mask |= (1 << d);
        val /= 10;
    }
    return mask;
}
  
// Function to count the number of ways
int countWays(int pos, int mask,
              int a[], int n)
{
    // Subarray must not be empty
    if (pos == n)
        return (mask > 0 ? 1 : 0);
  
    // If subproblem has been solved
    if (dp[pos][mask] != -1)
        return dp[pos][mask];
  
    int count = 0;
  
    // Excluding this element in the subarray
    count = count
            + countWays(pos + 1, mask, a, n);
  
    // If there are no common digits
    // then only this element can be included
    if ((getmask(a[pos]) & mask) == 0) {
  
        // Calculate the new mask
        // if this element is included
        int new_mask
            = (mask | (getmask(a[pos])));
  
        count = count
                + countWays(pos + 1,
                            new_mask,
                            a, n);
    }
  
    // Store and return the answer
    return dp[pos][mask] = count;
}
  
// Function to find the count of
// subarray with all digits unique
int numberOfSubarrays(int a[], int n)
{
    // intializing dp
    memset(dp, -1, sizeof(dp));
  
    return countWays(0, 0, a, n);
}
  
// Driver code
int main()
{
    int N = 4;
    int A[] = { 1, 12, 23, 34 };
  
    cout << numberOfSubarrays(A, N);
    return 0;
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to find the count
// of subarrays of an Array
// having all unique digits
import java.util.*;
  
class GFG{
   
// Dynamic programming table
static int [][]dp = new int[5000][(1 << 10) + 5];
   
// Function to obtain
// the mask for any integer
static int getmask(int val)
{
    int mask = 0;
   
    if (val == 0)
        return 1;
   
    while (val > 0) {
        int d = val % 10;
        mask |= (1 << d);
        val /= 10;
    }
    return mask;
}
   
// Function to count the number of ways
static int countWays(int pos, int mask,
              int a[], int n)
{
    // Subarray must not be empty
    if (pos == n)
        return (mask > 0 ? 1 : 0);
   
    // If subproblem has been solved
    if (dp[pos][mask] != -1)
        return dp[pos][mask];
   
    int count = 0;
   
    // Excluding this element in the subarray
    count = count
            + countWays(pos + 1, mask, a, n);
   
    // If there are no common digits
    // then only this element can be included
    if ((getmask(a[pos]) & mask) == 0) {
   
        // Calculate the new mask
        // if this element is included
        int new_mask
            = (mask | (getmask(a[pos])));
   
        count = count
                + countWays(pos + 1,
                            new_mask,
                            a, n);
    }
   
    // Store and return the answer
    return dp[pos][mask] = count;
}
   
// Function to find the count of
// subarray with all digits unique
static int numberOfSubarrays(int a[], int n)
{
    // intializing dp
    for(int i = 0;i<5000;i++)
    {
        for (int j = 0; j < (1 << 10) + 5; j++) {
            dp[i][j] = -1;
        }
    }
   
    return countWays(0, 0, a, n);
}
   
// Driver code
public static void main(String[] args)
{
    int N = 4;
    int A[] = { 1, 12, 23, 34 };
   
    System.out.print(numberOfSubarrays(A, N));
}
}
  
// This code is contributed by Princi Singh

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to find the count
// of subarrays of an Array
// having all unique digits
using System;
  
public class GFG{
  
// Dynamic programming table
static int [,]dp = new int[5000, (1 << 10) + 5];
  
// Function to obtain
// the mask for any integer
static int getmask(int val)
{
    int mask = 0;
  
    if (val == 0)
        return 1;
  
    while (val > 0) {
        int d = val % 10;
        mask |= (1 << d);
        val /= 10;
    }
    return mask;
}
  
// Function to count the number of ways
static int countWays(int pos, int mask,
            int []a, int n)
{
    // Subarray must not be empty
    if (pos == n)
        return (mask > 0 ? 1 : 0);
  
    // If subproblem has been solved
    if (dp[pos, mask] != -1)
        return dp[pos, mask];
  
    int count = 0;
  
    // Excluding this element in the subarray
    count = count
        + countWays(pos + 1, mask, a, n);
  
    // If there are no common digits
    // then only this element can be included
    if ((getmask(a[pos]) & mask) == 0) {
  
        // Calculate the new mask
        // if this element is included
        int new_mask
            = (mask | (getmask(a[pos])));
  
        count = count
            + countWays(pos + 1,
            new_mask, a, n);
    }
  
    // Store and return the answer
    return dp[pos, mask] = count;
}
  
// Function to find the count of
// subarray with all digits unique
static int numberOfSubarrays(int []a, int n)
{
    // intializing dp
    for(int i = 0; i < 5000; i++)
    {
        for (int j = 0; j < (1 << 10) + 5; j++) {
            dp[i,j] = -1;
        }
    }
  
    return countWays(0, 0, a, n);
}
  
// Driver code
public static void Main(String[] args)
{
    int N = 4;
    int []A = { 1, 12, 23, 34 };
  
    Console.Write(numberOfSubarrays(A, N));
}
}
// This code contributed by sapnasingh4991

chevron_right


Output:

7

Time Complexity: O(N * 210)

competitive-programming-img




My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.