Find Number of Unique Elements in an Array After each Query
Last Updated :
21 Dec, 2023
Given 2d array A[][1] of size N and array Q[][2] of size M representing M queries of type {a, b}. The task for this problem is in each query move all elements from A[a] to A[b] and print the number of unique elements in A[b].
Constraints:
- 1 <= N, Q <= 105
- 1 <= A[i] <= 109
- 1 <= a, b <= N
Examples:
Input: A[][1] = {{1}, {1}, {1}, {2}, {2}, {3}}, Q[][2] = {{1, 2}, {6, 4}, {5, 1}, {3, 6}, {4, 6}}
Output: 1 2 1 1 3
Explanation:
- For First query {1, 2} move all elements from A[1] to A[2]. A becomes {{}, {1, 1}, {1}, {2}, {2}, {3}}. Number of unique elements in A[2] is 1.
- For Second query {6, 4} move all elements from A[6] to A[4]. A becomes {{}, {1, 1}, {1}, {2, 3}, {2}, {}}. Number of unique elements in A[4] is 2.
- For Third query {5, 1} move all elements from A[5] to A[1]. A becomes {{2}, {1, 1}, {1}, {2, 3}, {}, {}}. Number of unique elements in A[1] is 1.
- For Fourth query {3, 6} move all elements from A[3] to A[6]. A becomes {{2}, {1, 1}, {}, {2, 3}, {}, {1}}. Number of unique elements in A[6] is 1.
- For Fifth query {4, 6} move all elements from A{4] to A[6]. A becomes {{2}, {1, 1}, {}, {}, {}, {1, 2, 3}}. Number of unique elements in A[6] is 3.
Input: A[][1] = {{2}, {4}, {2}, {4}, {2}}, Q[][2] = {{3, 1}, {2, 5}, {3, 2}}
Output: 1 2 0
Explanation:
- For First query {3, 1} move all elements from A[3] to A[1]. A becomes {{2, 2}, {4}, {}, {4}, {2}}. Number of unique elements in A[1] is 1.
- For Second query {2, 5} move all elements from A[2] to A[5]. A becomes {{2, 2}, {}, {}, {4}, {2, 4}}. Number of unique elements in A[5] is 2.
- For Third query {3, 2} move all elements from A[3] to A[2]. A becomes {{2, 2}, {}, {}, {4}, {2, 4}}. Number of unique elements in A[2] is 0.
Efficient Approach: To solve the problem follow the below idea.
This problem is an application of the “union-by-size / small-to-large heuristic”. This algorithm depends upon fact that swapping index of sets take place in constant time, and merging a smaller set of size M into a larger set of size N takes O(MlogN). When merging sets, always move from a smaller set to a larger set. So whenever we need to move some elements from larger to smaller set we just move smaller size set elements to larger size set elements and swap their indexes.
Below are the steps for the above approach:
- Declaring vector of sets V[N].
- Create an HashMap for dealing with the indexes.
- Insert all N arrays from A[][1] to N sets and initialize index map ind.
- Iterate for M queries and for each query
- Declare two variables x(which stores set which is to be moved) and y(which will take all incoming elements from other set).
- whenever we find elements in the set [x] is less than set[y] we insert elements in y set and if it is greater than set[y] then we insert all element in set [x] and swap their indexes.
- At the end of each query print the size of set V[ind[y]].
Below is the implementation of the above approach:
C++
// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
// Function to Queries to find
// number of unique elements in array
void queriesTofindUnique(int a[][1], int n, int Q[][2],
int m)
{
// Creating a vector of sets
vector<set<int> > v(n);
// Creating Map to find out which index pointing towards
// which index
unordered_map<int, int> ind;
for (int i = 0; i < n; i++) {
// Insert each value in the set of perticular index
v[i].insert(a[i][0]);
// Currently each index is pointing towards itself
ind[i] = i;
}
for (int i = 0; i < m; i++) {
int x = Q[i][0];
int y = Q[i][1];
// Making index Zero Based
--x;
--y;
if (v[ind[x]].size() <= v[ind[y]].size()) {
// Transfer all elements from x to y index
for (auto el : v[ind[x]])
v[ind[y]].insert(el);
// Clearing all values from 'x' index
v[ind[x]].clear();
}
else {
// Transfer all elements from y to x index
for (auto el : v[ind[y]])
v[ind[x]].insert(el);
// Clearing all values from 'y' index
v[ind[y]].clear();
// Now index x will point towards y and y
// towards x
swap(ind[x], ind[y]);
}
// printing the size of Q[i][1]
cout << v[ind[y]].size() << " ";
}
cout << "\n";
}
// Driver Code
int32_t main()
{
// Input 1
int N = 6, M = 5;
int A[][1]
= { { 1 }, { 1 }, { 1 }, { 2 }, { 2 }, { 3 } };
int Q[][2] = {
{ 1, 2 }, { 6, 4 }, { 5, 1 }, { 3, 6 }, { 4, 6 }
};
// Function Call
queriesTofindUnique(A, N, Q, M);
return 0;
}
Java
/*code by Flutterfly */
import java.util.*;
public class Main {
// Function to Queries to find
// number of unique elements in array
static void queriesToFindUnique(int[][] a, int n, int[][] Q, int m) {
// Creating a vector of sets
ArrayList<HashSet<Integer>> v = new ArrayList<>(n);
// Creating Map to find out which index pointing towards
// which index
HashMap<Integer, Integer> ind = new HashMap<>();
for (int i = 0; i < n; i++) {
// Insert each value in the set of particular index
HashSet<Integer> set = new HashSet<>();
set.add(a[i][0]);
v.add(set);
// Currently each index is pointing towards itself
ind.put(i, i);
}
for (int i = 0; i < m; i++) {
int x = Q[i][0];
int y = Q[i][1];
// Making index Zero Based
--x;
--y;
if (v.get(ind.get(x)).size() <= v.get(ind.get(y)).size()) {
// Transfer all elements from x to y index
for (int el : v.get(ind.get(x))) {
v.get(ind.get(y)).add(el);
}
// Clearing all values from 'x' index
v.get(ind.get(x)).clear();
} else {
// Transfer all elements from y to x index
for (int el : v.get(ind.get(y))) {
v.get(ind.get(x)).add(el);
}
// Clearing all values from 'y' index
v.get(ind.get(y)).clear();
// Now index x will point towards y and y
// towards x
Collections.swap(v, ind.get(x), ind.get(y));
}
// printing the size of Q[i][1]
System.out.print(v.get(ind.get(y)).size() + " ");
}
System.out.println();
}
// Driver Code
public static void main(String[] args) {
// Input 1
int N = 6, M = 5;
int[][] A = {{1}, {1}, {1}, {2}, {2}, {3}};
int[][] Q = {
{1, 2}, {6, 4}, {5, 1}, {3, 6}, {4, 6}
};
// Function Call
queriesToFindUnique(A, N, Q, M);
}
}
Python3
def queries_to_find_unique(a, n, q, m):
"""
Function to Queries to find number of unique elements in array
"""
# Creating a list of sets
v = [set([a[i][0]]) for i in range(n)]
# Creating Map to find out which index pointing towards
# which index
ind = {i: i for i in range(n)}
for i in range(m):
x, y = q[i][0], q[i][1]
# Making index Zero Based
x -= 1
y -= 1
if len(v[ind[x]]) <= len(v[ind[y]]):
# Transfer all elements from x to y index
v[ind[y]].update(v[ind[x]])
# Clearing all values from 'x' index
v[ind[x]].clear()
else:
# Transfer all elements from y to x index
v[ind[x]].update(v[ind[y]])
# Clearing all values from 'y' index
v[ind[y]].clear()
# Now index x will point towards y and y towards x
ind[x], ind[y] = ind[y], ind[x]
# Printing the size of Q[i][1]
print(len(v[ind[y]]), end=" ")
print("\n")
# Driver Code
if __name__ == "__main__":
# Input 1
N, M = 6, 5
A = [[1], [1], [1], [2], [2], [3]]
Q = [[1, 2], [6, 4], [5, 1], [3, 6], [4, 6]]
# Function Call
queries_to_find_unique(A, N, Q, M)
C#
//code by Flutterfly
using System;
using System.Collections.Generic;
public class MainClass
{
// Function to Queries to find
// number of unique elements in array
static void QueriesToFindUnique(int[][] a, int n, int[][] Q, int m)
{
// Creating a List of Sets
List<HashSet<int>> v = new List<HashSet<int>>(n);
// Creating Dictionary to find out which index pointing towards
// which index
Dictionary<int, int> ind = new Dictionary<int, int>();
for (int i = 0; i < n; i++)
{
// Insert each value in the set of particular index
HashSet<int> set = new HashSet<int>();
set.Add(a[i][0]);
v.Add(set);
// Currently each index is pointing towards itself
ind[i] = i;
}
for (int i = 0; i < m; i++)
{
int x = Q[i][0];
int y = Q[i][1];
// Making index Zero Based
--x;
--y;
if (v[ind[x]].Count <= v[ind[y]].Count)
{
// Transfer all elements from x to y index
foreach (int el in v[ind[x]])
{
v[ind[y]].Add(el);
}
// Clearing all values from 'x' index
v[ind[x]].Clear();
}
else
{
// Transfer all elements from y to x index
foreach (int el in v[ind[y]])
{
v[ind[x]].Add(el);
}
// Clearing all values from 'y' index
v[ind[y]].Clear();
// Now index x will point towards y and y
// towards x
int temp = ind[x];
ind[x] = ind[y];
ind[y] = temp;
}
// printing the size of Q[i][1]
Console.Write(v[ind[y]].Count + " ");
}
Console.WriteLine();
}
// Driver Code
public static void Main(string[] args)
{
// Input 1
int N = 6, M = 5;
int[][] A = { new[] { 1 }, new[] { 1 }, new[] { 1 }, new[] { 2 }, new[] { 2 }, new[] { 3 } };
int[][] Q = {
new[] { 1, 2 }, new[] { 6, 4 }, new[] { 5, 1 }, new[] { 3, 6 }, new[] { 4, 6 }
};
// Function Call
QueriesToFindUnique(A, N, Q, M);
}
}
JavaScript
//code by Flutterfly
// Function to Queries to find
// number of unique elements in array
function queriesToFindUnique(a, n, Q, m) {
// Creating an array of sets
let v = new Array(n).fill(null).map(() => new Set());
// Creating Map to find out which index pointing towards
// which index
let ind = new Map();
for (let i = 0; i < n; i++) {
// Insert each value in the set of particular index
v[i].add(a[i][0]);
// Currently each index is pointing towards itself
ind.set(i, i);
}
for (let i = 0; i < m; i++) {
let x = Q[i][0];
let y = Q[i][1];
// Making index Zero Based
--x;
--y;
if (v[ind.get(x)].size <= v[ind.get(y)].size) {
// Transfer all elements from x to y index
for (let el of v[ind.get(x)]) {
v[ind.get(y)].add(el);
}
// Clearing all values from 'x' index
v[ind.get(x)].clear();
} else {
// Transfer all elements from y to x index
for (let el of v[ind.get(y)]) {
v[ind.get(x)].add(el);
}
// Clearing all values from 'y' index
v[ind.get(y)].clear();
// Now index x will point towards y and y
// towards x
let temp = ind.get(x);
ind.set(x, ind.get(y));
ind.set(y, temp);
}
// printing the size of Q[i][1]
process.stdout.write(v[ind.get(y)].size + " ");
}
console.log();
}
// Driver Code
// Input 1
let N = 6, M = 5;
let A = [[1], [1], [1], [2], [2], [3]];
let Q = [
[1, 2], [6, 4], [5, 1], [3, 6], [4, 6]
];
// Function Call
queriesToFindUnique(A, N, Q, M);
Time Complexity: O(Nlog2N)
Auxiliary Space: O(N)
Similar Reads
Find sum of all unique elements in the array for K queries Given an arrays arr[] in which initially all elements are 0 and another array Q[][] containing K queries where every query represents a range [L, R], the task is to add 1 to each subarrays where each subarray is defined by the range [L, R], and return sum of all unique elements.Note: One-based index
8 min read
Print all unique elements present in a sorted array Given a sorted array arr[] of size N, the task is to print all the unique elements in the array. An array element is said to be unique if the frequency of that element in the array is 1. Examples: Input: arr[ ] = {1, 1, 2, 2, 3, 4, 5, 5}Output: 3 4Explanation: Since 1, 2, 5 are occurring more than o
5 min read
Queries for number of distinct elements from a given index till last index in an array Given a array âa[]â of size n and number of queries q. Each query can be represented by a integer m. Your task is to print the number of distinct integers from index m to n i.e till last element of the array. Examples: Input: arr[] = {1, 2, 3, 1, 2, 3, 4, 5}, q[] = {1, 4, 6, 8} Output: 5 5 3 1 In qu
6 min read
Queries for number of distinct elements in a subarray Given a array 'a[]' of size n and number of queries q. Each query can be represented by two integers l and r. Your task is to print the number of distinct integers in the subarray l to r. Given a[i] <= 106 Examples: Input : a[] = {1, 1, 2, 1, 3} q = 3 0 4 1 3 2 4 Output :3 2 3 In query 1, number
10 min read
Minimum length subarray containing all unique elements after Q operations Given an array of size N containing all elements as 0 initially, and a Q queries containing range in the form of [L, R]. The task is to modify the array by adding 1 to each element in the range [L, R] for Q queries and then print the size of minimum length subarray containing all unique elements.Not
11 min read
Unique element in an array where all elements occur k times except one Given an array that contains all elements occurring k times, but one occurs only once. Find that unique element.Examples: Input : arr[] = {6, 2, 5, 2, 2, 6, 6} k = 3Output : 5Explanation: Every element appears 3 times accept 5. Input : arr[] = {2, 2, 2, 10, 2} k = 4Output: 10Explanation: Every eleme
13 min read