Given an integer array arr[]. Count the number of subarrays whose number of distinct elements is exactly the same as the number of distinct elements in the entire array. A subarray is a contiguous part of the array.
Examples:
Input: arr[] = [2, 1, 3, 2, 3]
Output: 5
Explanation:
The entire array contains 3 distinct elements: [1, 2, 3].
The subarrays that also contain all 3 distinct elements are:
arr[0..2] = [2, 1, 3]
arr[0..3] = [2, 1, 3, 2]
arr[0..4] = [2, 1, 3, 2, 3]
arr[1..3] = [1, 3, 2]
arr[1..4] = [1, 3, 2, 3]
Hence, the total number of such subarrays is 5.
Input: arr[] = [2, 4, 4, 2, 4]
Output: 9
Explanation: The entire array contains 2 distinct elements: [2, 4].
Therefore, we need to count all subarrays that contain both 2 and 4.
The valid subarrays are:
arr[0..1] = [2, 4]
arr[0..2] = [2, 4, 4]
arr[0..3] = [2, 4, 4, 2]
arr[0..4] = [2, 4, 4, 2, 4]
arr[1..3] = [4, 4, 2]
arr[1..4] = [4, 4, 2, 4]
arr[2..3] = [4, 2]
arr[2..4] = [4, 2, 4]
arr[3..4] = [2, 4]
Hence, the total number of such subarrays is 9.
Table of Content
[Naive Approach] Subarray Traversal with Hashing - O(n^2) Time and O(n) Space
- Traverse all possible subarrays of the array.
- For each subarray, use a hash set to store elements and count the number of distinct elements.
- If the count of distinct elements equals the total distinct elements in the original array, increase the answer count.
#include <iostream>
#include <unordered_set>
#include <vector>
using namespace std;
int countAllDistinct(vector<int> &arr)
{
// count distinct elements in the whole array
unordered_set<int> st;
for (int x : arr)
st.insert(x);
int d = st.size();
// count valid subarrays
int n = arr.size();
int ans = 0;
for (int i = 0; i < n; i++)
{
// set to count distinct
// elements in current subarray
unordered_set<int> temp;
for (int j = i; j < n; j++)
{
temp.insert(arr[j]);
// if distinct count matches
if ((int)temp.size() == d)
ans++;
}
}
return ans;
}
int main()
{
vector<int> arr = {2, 4, 4, 2, 4};
cout << countAllDistinct(arr);
return 0;
}
import java.util.HashSet;
public class GFG {
public static int countAllDistinct(int[] arr)
{
// count distinct elements in the whole array
HashSet<Integer> st = new HashSet<>();
for (int x : arr)
st.add(x);
int d = st.size();
// count valid subarrays
int n = arr.length;
int ans = 0;
for (int i = 0; i < n; i++) {
// set to count distinct
// elements in current subarray
HashSet<Integer> temp = new HashSet<>();
for (int j = i; j < n; j++) {
temp.add(arr[j]);
// if distinct count matches
if (temp.size() == d)
ans++;
}
}
return ans;
}
public static void main(String[] args)
{
int[] arr = { 2, 4, 4, 2, 4 };
System.out.println(countAllDistinct(arr));
}
}
def countAllDistinct(arr):
# count distinct elements in the whole array
st = set(arr)
d = len(st)
# count valid subarrays
n = len(arr)
ans = 0
for i in range(n):
# set to count distinct
# elements in current subarray
temp = set()
for j in range(i, n):
temp.add(arr[j])
# if distinct count matches
if len(temp) == d:
ans += 1
return ans
if __name__ == "__main__":
arr = [2, 4, 4, 2, 4]
print(countAllDistinct(arr))
using System;
using System.Collections.Generic;
public class GFG {
public static int countAllDistinct(int[] arr)
{
// count distinct elements in the whole array
HashSet<int> st = new HashSet<int>(arr);
int d = st.Count;
// count valid subarrays
int n = arr.Length;
int ans = 0;
for (int i = 0; i < n; i++) {
// set to count distinct
// elements in current subarray
HashSet<int> temp = new HashSet<int>();
for (int j = i; j < n; j++) {
temp.Add(arr[j]);
// if distinct count matches
if (temp.Count == d)
ans++;
}
}
return ans;
}
public static void Main()
{
int[] arr = { 2, 4, 4, 2, 4 };
Console.WriteLine(countAllDistinct(arr));
}
}
function countAllDistinct(arr)
{
// count distinct elements in the whole array
let st = new Set(arr);
let d = st.size;
// count valid subarrays
let n = arr.length;
let ans = 0;
for (let i = 0; i < n; i++) {
// set to count distinct
// elements in current subarray
let temp = new Set();
for (let j = i; j < n; j++) {
temp.add(arr[j]);
// if distinct count matches
if (temp.size === d)
ans++;
}
}
return ans;
}
let arr = [ 2, 4, 4, 2, 4 ];
console.log(countAllDistinct(arr));
Output
9
[Expected Approach] Sliding Window with Hashing - O(n) Time and O(n) Space
- Use a sliding window with two pointers l (start) and r (end) to maintain a dynamic subarray.
- Maintain a hash map to store the distinct elements currently present in the window.
- Fix the starting index l and expand r until the window [l, r] contains all distinct elements of the array.
- Once the window becomes valid, all larger windows [l, r+1], [l, r+2] ... will also remain valid, so count all such subarrays together. Then move l forward, update the hash map accordingly, and repeat the process for the next window.
#include <iostream>
#include <map>
#include <vector>
using namespace std;
int countAllDistinct(vector<int> &arr)
{
int n = arr.size();
unordered_map<int, int> vis;
// count total distinct elements
for (int x : arr)
vis[x] = 1;
int k = vis.size();
vis.clear();
int ans = 0, right = 0, window = 0;
for (int left = 0; left < n; left++)
{
// expand window until all distinct elements are included
while (right < n && window < k)
{
vis[arr[right]]++;
if (vis[arr[right]] == 1)
window++;
right++;
}
// if valid window, count subarrays
if (window == k)
ans += (n - right + 1);
// shrink window from left
vis[arr[left]]--;
if (vis[arr[left]] == 0)
window--;
}
return ans;
}
int main()
{
vector<int> arr = {2, 4, 4, 2, 4};
cout << countAllDistinct(arr);
return 0;
}
import java.util.HashMap;
import java.util.Map;
public class GFG {
public static int countAllDistinct(int[] arr)
{
int n = arr.length;
Map<Integer, Integer> vis = new HashMap<>();
// count total distinct elements
for (int x : arr)
vis.put(x, 1);
int k = vis.size();
vis.clear();
int ans = 0, right = 0, window = 0;
for (int left = 0; left < n; left++) {
// expand window until all distinct elements are
// included
while (right < n && window < k) {
vis.put(arr[right],
vis.getOrDefault(arr[right], 0)
+ 1);
if (vis.get(arr[right]) == 1)
window++;
right++;
}
// if valid window, count subarrays
if (window == k)
ans += (n - right + 1);
// shrink window from left
vis.put(arr[left], vis.get(arr[left]) - 1);
if (vis.get(arr[left]) == 0)
window--;
}
return ans;
}
public static void main(String[] args)
{
int[] arr = { 2, 4, 4, 2, 4 };
System.out.println(countAllDistinct(arr));
}
}
def countAllDistinct(arr):
n = len(arr)
vis = {}
# count total distinct elements
for x in arr:
vis[x] = 1
k = len(vis)
vis.clear()
ans = 0
right = 0
window = 0
for left in range(n):
# expand window until all distinct elements are included
while right < n and window < k:
if arr[right] in vis:
vis[arr[right]] += 1
else:
vis[arr[right]] = 1
if vis[arr[right]] == 1:
window += 1
right += 1
# if valid window, count subarrays
if window == k:
ans += (n - right + 1)
# shrink window from left
if vis[arr[left]] == 1:
window -= 1
vis[arr[left]] -= 1
return ans
if __name__ == '__main__':
arr = [2, 4, 4, 2, 4]
print(countAllDistinct(arr))
using System;
using System.Collections.Generic;
public class GFG {
public static int countAllDistinct(int[] arr)
{
int n = arr.Length;
Dictionary<int, int> vis
= new Dictionary<int, int>();
// count total distinct elements
foreach(int x in arr) vis[x] = 1;
int k = vis.Count;
vis.Clear();
int ans = 0, right = 0, window = 0;
for (int left = 0; left < n; left++) {
// expand window until all distinct elements are
// included
while (right < n && window < k) {
if (vis.ContainsKey(arr[right]))
vis[arr[right]]++;
else
vis[arr[right]] = 1;
if (vis[arr[right]] == 1)
window++;
right++;
}
// if valid window, count subarrays
if (window == k)
ans += (n - right + 1);
// shrink window from left
if (vis[arr[left]] == 1)
window--;
vis[arr[left]]--;
}
return ans;
}
public static void Main()
{
int[] arr = { 2, 4, 4, 2, 4 };
Console.WriteLine(countAllDistinct(arr));
}
}
function countAllDistinct(arr)
{
let n = arr.length;
let vis = new Map();
// count total distinct elements
for (let x of arr) {
vis.set(x, 1);
}
let k = vis.size;
vis.clear();
let ans = 0, right = 0, window = 0;
for (let left = 0; left < n; left++) {
// expand window until all distinct elements are
// included
while (right < n && window < k) {
vis.set(arr[right],
(vis.get(arr[right]) || 0) + 1);
if (vis.get(arr[right]) === 1)
window++;
right++;
}
// if valid window, count subarrays
if (window === k)
ans += (n - right + 1);
// shrink window from left
vis.set(arr[left], vis.get(arr[left]) - 1);
if (vis.get(arr[left]) === 0)
window--;
}
return ans;
}
// Driver Code
console.log(countAllDistinct([ 2, 4, 4, 2, 4 ]));
Output
9