Given a list of contacts containing the username, email and phone number in any order. Identify the same contacts (i.e., the same person having many contacts) and output the same contacts together.

Notes:

1) A contact can store its three fields in any order, i.e., a phone number can appear before username or username can appear before the phone number.

2) Two contacts are the same if they have either the same username or email or phone number.

**Example:**

Input: contact[] = { {"Gaurav", "gaurav@gmail.com", "gaurav@gfgQA.com"}, { "Lucky", "lucky@gmail.com", "+1234567"}, { "gaurav123", "+5412312", "gaurav123@skype.com"}. { "gaurav1993", "+5412312", "gaurav@gfgQA.com"} } Output: 0 2 3 1 contact[2] is same as contact[3] because they both have same contact number. contact[0] is same as contact[3] because they both have same e-mail address. Therefore, contact[0] and contact[2] are also same.

**We strongly recommend you to minimize your browser and try this yourself first.**

Input is basically an array of structures. A structure contains three fields such that any field can represent any detail about a contact.

The idea is to first create a graph of contacts using given array. In the graph, there is an edge between vertex i to vertex j if they both have either same username or same email or same phone number. Once the graph is constructed, the task reduces to finding connected components in an undirected graph. We can find connected components either by doing DFS or BFS starting from every unvisited vertex. In below code, DFS is used.

Below is implementation of this idea.

## C++

`// A C++ program to find same contacts in a list of contacts` `#include<bits/stdc++.h>` `using` `namespace` `std;` `// Structure for storing contact details.` `struct` `contact` `{` ` ` `string field1, field2, field3;` `};` `// A utility function to fill entries in adjacency matrix` `// representation of graph` `void` `buildGraph(contact arr[], ` `int` `n, ` `int` `*mat[])` `{` ` ` `// Initialize the adjacency matrix` ` ` `for` `(` `int` `i=0; i<n; i++)` ` ` `for` `(` `int` `j=0; j<n; j++)` ` ` `mat[i][j] = 0;` ` ` `// Traverse through all contacts` ` ` `for` `(` `int` `i = 0; i < n; i++) {` ` ` `// Add mat from i to j and vice versa, if possible.` ` ` `// Since length of each contact field is at max some` ` ` `// constant. (say 30) so body execution of this for` ` ` `// loop takes constant time.` ` ` `for` `(` `int` `j = i+1; j < n; j++)` ` ` `if` `(arr[i].field1 == arr[j].field1 ||` ` ` `arr[i].field1 == arr[j].field2 ||` ` ` `arr[i].field1 == arr[j].field3 ||` ` ` `arr[i].field2 == arr[j].field1 ||` ` ` `arr[i].field2 == arr[j].field2 ||` ` ` `arr[i].field2 == arr[j].field3 ||` ` ` `arr[i].field3 == arr[j].field1 ||` ` ` `arr[i].field3 == arr[j].field2 ||` ` ` `arr[i].field3 == arr[j].field3)` ` ` `{` ` ` `mat[i][j] = 1;` ` ` `mat[j][i] = 1;` ` ` `break` `;` ` ` `}` ` ` `}` `}` `// A recuesive function to perform DFS with vertex i as source` `void` `DFSvisit(` `int` `i, ` `int` `*mat[], ` `bool` `visited[], vector<` `int` `>& sol, ` `int` `n)` `{` ` ` `visited[i] = ` `true` `;` ` ` `sol.push_back(i);` ` ` `for` `(` `int` `j = 0; j < n; j++)` ` ` `if` `(mat[i][j] && !visited[j])` ` ` `DFSvisit(j, mat, visited, sol, n);` `}` `// Finds similar contacrs in an array of contacts` `void` `findSameContacts(contact arr[], ` `int` `n)` `{` ` ` `// vector for storing the solution` ` ` `vector<` `int` `> sol;` ` ` `// Declare 2D adjaceny matrix for mats` ` ` `int` `**mat = ` `new` `int` `*[n];` ` ` `for` `(` `int` `i = 0; i < n; i++)` ` ` `mat[i] = ` `new` `int` `[n];` ` ` `// visited array to keep track of visited nodes` ` ` `bool` `visited[n];` ` ` `memset` `(visited, 0, ` `sizeof` `(visited));` ` ` `// Fill adjacency matrix` ` ` `buildGraph(arr, n, mat);` ` ` `// Since, we made a graph with contacts as nodes with fields as links.` ` ` `// two nodes are linked if they represent the same person.` ` ` `// so, total number of connected components and nodes in each component` ` ` `// will be our answer.` ` ` `for` `(` `int` `i = 0; i < n; i++)` ` ` `{` ` ` `if` `(!visited[i])` ` ` `{` ` ` `DFSvisit(i, mat, visited, sol, n);` ` ` `// Add delimeter to separate nodes of one component from other.` ` ` `sol.push_back(-1);` ` ` `}` ` ` `}` ` ` `// Print the solution` ` ` `for` `(` `int` `i = 0; i < sol.size(); i++)` ` ` `if` `(sol[i] == -1) cout << endl;` ` ` `else` `cout << sol[i] << ` `" "` `;` `}` `// Drive Code` `int` `main()` `{` ` ` `contact arr[] = {{` `"Gaurav"` `, ` `"gaurav@gmail.com"` `, ` `"gaurav@gfgQA.com"` `},` ` ` `{` `"Lucky"` `, ` `"lucky@gmail.com"` `, ` `"+1234567"` `},` ` ` `{` `"gaurav123"` `, ` `"+5412312"` `, ` `"gaurav123@skype.com"` `},` ` ` `{` `"gaurav1993"` `, ` `"+5412312"` `, ` `"gaurav@gfgQA.com"` `},` ` ` `{` `"raja"` `, ` `"+2231210"` `, ` `"raja@gfg.com"` `},` ` ` `{` `"bahubali"` `, ` `"+878312"` `, ` `"raja"` `}` ` ` `};` ` ` `int` `n = ` `sizeof` `arr / ` `sizeof` `arr[0];` ` ` `findSameContacts(arr, n);` ` ` `return` `0;` `}` |

*chevron_right*

*filter_none*

## Python3

`# A Python3 program to find same contacts` `# in a list of contacts ` `# Structure for storing contact details. ` `class` `contact:` ` ` `def` `__init__(` `self` `, field1, ` ` ` `field2, field3):` ` ` `self` `.field1 ` `=` `field1` ` ` `self` `.field2 ` `=` `field2` ` ` `self` `.field3 ` `=` `field3` `# A utility function to fill entries in ` `# adjacency matrix representation of graph ` `def` `buildGraph(arr, n, mat):` ` ` ` ` `# Initialize the adjacency matrix` ` ` `for` `i ` `in` `range` `(n):` ` ` `for` `j ` `in` `range` `(n):` ` ` `mat[i][j] ` `=` `0` ` ` `# Traverse through all contacts ` ` ` `for` `i ` `in` `range` `(n):` ` ` `# Add mat from i to j and vice versa, ` ` ` `# if possible. Since length of each ` ` ` `# contact field is at max some constant.` ` ` `# (say 30) so body execution of this for ` ` ` `# loop takes constant time.` ` ` `for` `j ` `in` `range` `(i ` `+` `1` `, n):` ` ` `if` `(arr[i].field1 ` `=` `=` `arr[j].field1 ` `or` ` ` `arr[i].field1 ` `=` `=` `arr[j].field2 ` `or` ` ` `arr[i].field1 ` `=` `=` `arr[j].field3 ` `or` ` ` `arr[i].field2 ` `=` `=` `arr[j].field1 ` `or` ` ` `arr[i].field2 ` `=` `=` `arr[j].field2 ` `or` ` ` `arr[i].field2 ` `=` `=` `arr[j].field3 ` `or` ` ` `arr[i].field3 ` `=` `=` `arr[j].field1 ` `or` ` ` `arr[i].field3 ` `=` `=` `arr[j].field2 ` `or` ` ` `arr[i].field3 ` `=` `=` `arr[j].field3):` ` ` `mat[i][j] ` `=` `1` ` ` `mat[j][i] ` `=` `1` ` ` `break` `# A recuesive function to perform DFS ` `# with vertex i as source ` `def` `DFSvisit(i, mat, visited, sol, n):` ` ` `visited[i] ` `=` `True` ` ` `sol.append(i) ` ` ` `for` `j ` `in` `range` `(n):` ` ` `if` `(mat[i][j] ` `and` `not` `visited[j]):` ` ` `DFSvisit(j, mat, visited, sol, n)` `# Finds similar contacrs in an` `# array of contacts ` `def` `findSameContacts(arr, n):` ` ` ` ` `# vector for storing the solution ` ` ` `sol ` `=` `[]` ` ` `# Declare 2D adjaceny matrix for mats ` ` ` `mat ` `=` `[[` `None` `] ` `*` `n ` `for` `i ` `in` `range` `(n)] ` ` ` `# visited array to keep track` ` ` `# of visited nodes ` ` ` `visited ` `=` `[` `0` `] ` `*` `n` ` ` `# Fill adjacency matrix ` ` ` `buildGraph(arr, n, mat) ` ` ` `# Since, we made a graph with contacts ` ` ` `# as nodes with fields as links. Two ` ` ` `# nodes are linked if they represent` ` ` `# the same person. So, total number of ` ` ` `# connected components and nodes in each` ` ` `# component will be our answer.` ` ` `for` `i ` `in` `range` `(n):` ` ` `if` `(` `not` `visited[i]):` ` ` `DFSvisit(i, mat, visited, sol, n) ` ` ` `# Add delimeter to separate nodes` ` ` `# of one component from other. ` ` ` `sol.append(` `-` `1` `)` ` ` `# Print the solution` ` ` `for` `i ` `in` `range` `(` `len` `(sol)):` ` ` `if` `(sol[i] ` `=` `=` `-` `1` `):` ` ` `print` `()` ` ` `else` `:` ` ` `print` `(sol[i], end ` `=` `" "` `)` `# Driver Code ` `if` `__name__ ` `=` `=` `'__main__'` `: ` ` ` `arr ` `=` `[contact(` `"Gaurav"` `, ` `"gaurav@gmail.com"` `, ` `"gaurav@gfgQA.com"` `), ` ` ` `contact(` `"Lucky"` `, ` `"lucky@gmail.com"` `, ` `"+1234567"` `), ` ` ` `contact(` `"gaurav123"` `, ` `"+5412312"` `, ` `"gaurav123@skype.com"` `), ` ` ` `contact(` `"gaurav1993"` `, ` `"+5412312"` `, ` `"gaurav@gfgQA.com"` `), ` ` ` `contact(` `"raja"` `, ` `"+2231210"` `, ` `"raja@gfg.com"` `),` ` ` `contact(` `"bahubali"` `, ` `"+878312"` `, ` `"raja"` `)]` ` ` `n ` `=` `len` `(arr) ` ` ` `findSameContacts(arr, n)` `# This code is contributed by PranchalK` |

*chevron_right*

*filter_none*

**Output:**

0 3 2 1 4 5

**Time complexity:** O(n^{2}) where n is number of contacts.

Thanks to Gaurav Ahirwar for above solution.

**Another Approach: (Using Union Find) **

The problem can be solved with Union Find as well. Here, we unify all the people who have at least one common contact. We need to isolate all the indices which have common contacts. To achieve this, we can maintain an array of the map of indices for each contact and unify all the indices corresponding to them. After the Union Find, we get Disjoint Sets which are distinct people.

## CPP14

`// CPP14 program to find common contacts.` `#include <bits/stdc++.h>` `using` `namespace` `std;` `// The class DSU will implement the Union Find` `class` `DSU {` ` ` `vector<` `int` `> parent, size;` `public` `:` ` ` `// In the constructor, we assign the each index as its` ` ` `// own parent and size as the number of contacts` ` ` `// available for that index` ` ` `DSU(vector<vector<string> >& contacts)` ` ` `{` ` ` `for` `(` `int` `i = 0; i < contacts.size(); i++) {` ` ` `parent.push_back(i);` ` ` `size.push_back(contacts[i].size());` ` ` `}` ` ` `}` ` ` `// Finds the set in which the element belongs. Path` ` ` `// compression is used to optimise time complexity` ` ` `int` `findSet(` `int` `v)` ` ` `{` ` ` `if` `(v == parent[v])` ` ` `return` `v;` ` ` `return` `parent[v] = findSet(parent[v]);` ` ` `}` ` ` `// Unifies the sets a and b where, the element belonging` ` ` `// to the smaller set is merged to the one belonging to` ` ` `// the smaller set` ` ` `void` `unionSet(` `int` `a, ` `int` `b, vector<string>& person1,` ` ` `vector<string>& person2)` ` ` `{` ` ` `if` `(size[a] > size[b]) {` ` ` `parent[b] = a;` ` ` `size[a] += size[b];` ` ` `for` `(` `auto` `contact : person2)` ` ` `person1.push_back(contact);` ` ` `}` ` ` `else` `{` ` ` `parent[a] = b;` ` ` `size[b] += size[a];` ` ` `for` `(` `auto` `contact : person1)` ` ` `person2.push_back(contact);` ` ` `}` ` ` `}` `};` `// Driver Code` `int` `main()` `{` ` ` `vector<vector<string> > contacts = {` ` ` `{ ` `"Gaurav"` `, ` `"gaurav@gmail.com"` `,` ` ` `"gaurav@gfgQA.com"` `},` ` ` `{ ` `"Lucky"` `, ` `"lucky@gmail.com"` `, ` `"+1234567"` `},` ` ` `{ ` `"gaurav123"` `, ` `"+5412312"` `, ` `"gaurav123@skype.com"` `},` ` ` `{ ` `"gaurav1993"` `, ` `"+5412312"` `, ` `"gaurav@gfgQA.com"` `},` ` ` `{ ` `"raja"` `, ` `"+2231210"` `, ` `"raja@gfg.com"` `},` ` ` `{ ` `"bahubali"` `, ` `"+878312"` `, ` `"raja"` `}` ` ` `};` ` ` `// Initializing the object of DSU class` ` ` `DSU dsu(contacts);` ` ` `// Will contain the mapping of a contact to all the` ` ` `// indices it is present within` ` ` `unordered_map<string, vector<` `int` `> > contactToIndex;` ` ` `for` `(` `int` `index = 0; index < contacts.size(); index++) {` ` ` `for` `(` `auto` `contact : contacts[index])` ` ` `contactToIndex[contact].push_back(index);` ` ` `}` ` ` `// Unifies the sets of each contact if they are not` ` ` `// present in the same set` ` ` `for` `(` `auto` `contact : contactToIndex) {` ` ` `vector<` `int` `> indices = contact.second;` ` ` `for` `(` `int` `i = 0; i < indices.size() - 1; i++) {` ` ` `int` `set1 = dsu.findSet(indices[i]),` ` ` `set2 = dsu.findSet(indices[i + 1]);` ` ` `if` `(set1 != set2)` ` ` `dsu.unionSet(set1, set2, contacts[set1],` ` ` `contacts[set2]);` ` ` `}` ` ` `}` ` ` `// Contains a map of all the distinct sets available` ` ` `// after union find has been completed` ` ` `unordered_map<` `int` `, vector<` `int` `> > unifiedSet;` ` ` `// All parents are mapped to the elemets in the set` ` ` `for` `(` `int` `i = 0; i < contacts.size(); i++) {` ` ` `unifiedSet[dsu.findSet(i)].push_back(i);` ` ` `}` ` ` `// Printing out elements from distict sets` ` ` `for` `(` `auto` `eachSet : unifiedSet) {` ` ` `for` `(` `auto` `element : eachSet.second)` ` ` `cout << element << ` `" "` `;` ` ` `cout << endl;` ` ` `}` ` ` `return` `0;` `}` |

*chevron_right*

*filter_none*

**Output**

4 5 0 2 3 1

**Time Complexity: **O(N * α(N)) where N is the number of contacts and α is the Inverse Ackermann Function**Space Complexity: **O(N)

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the **DSA Self Paced Course** at a student-friendly price and become industry ready.