Related Articles

Related Articles

Find same contacts in a list of contacts
  • Difficulty Level : Medium
  • Last Updated : 26 Sep, 2020

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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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


Output: 
 



0 3 2
1
4 5

Time complexity: O(n2) 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

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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


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.




My Personal Notes arrow_drop_up
Recommended Articles
Page :