Find same contacts in a list of contacts

28 Jun, 2022
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: 
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.Two contacts are the same if they have either the same username or email or phone number. 
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.
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++
Python3
// 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 graphvoid 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 recursive function to perform DFS with vertex i as sourcevoid 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 contacts in an array of contactsvoid findSameContacts(contact arr[], int n){    // vector for storing the solution    vector<int> sol;     // Declare 2D adjacency 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 delimiter 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 Codeint 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;}
# 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 graphdef 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 recursive function to perform DFS# with vertex i as sourcedef 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 contacts in an# array of contactsdef findSameContacts(arr, n):         # vector for storing the solution    sol = []     # Declare 2D adjacency 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 delimiter 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 Codeif __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
0 3 2 
1 
4 5 

Time complexity: O(n2) where n is number of contacts.
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.
C++14
// CPP14 program to find common contacts.#include <bits/stdc++.h>using namespace std; // The class DSU will implement the Union Findclass 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 Codeint 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 elements in the set    for (int i = 0; i < contacts.size(); i++) {         unifiedSet[dsu.findSet(i)].push_back(i);    }     // Printing out elements from distinct sets    for (auto eachSet : unifiedSet) {         for (auto element : eachSet.second)            cout << element << " ";         cout << endl;    }     return 0;}
4 5 
0 2 3 
1 

Time Complexity: O(N * α(N)) where N is the number of contacts and α is the Inverse Ackermann FunctionSpace Complexity: O(N)
PranchalKatiyar
nidhi_biet
veedee
simmytarika5
anikakapoor
sagartomar9927
anikaseth98
saurabh1990aror
surindertarika1234
hardikkoriintern
BFS
DFS
Graph
DFS
Graph
BFS
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Find if there is a path between two vertices in a directed graph
Introduction to Data Structures
Find if there is a path between two vertices in an undirected graph
What is Data Structure: Types, Classifications and Applications
Top 50 Graph Coding Problems for Interviews
K Centers Problem | Set 1 (Greedy Approximate Algorithm)
Bridges in a graph
Real-time application of Data Structures
Longest Path in a Directed Acyclic Graph
Water Jug problem using BFS