Leetcode: The Earliest Moment When Everyone Become Friends


This question is asked at Google and Expedia and is as follows: 

In a social group, there are N people with unique integer ids from 0 to N - 1.

We have a list of logs where each logs[i] = [timestamp, id_A, id_B] contains a non-negative integer timestamp and the ids of two different people, and each log represents the time in which two different people becomes friends and is symmetric: if A is friends with B, then B is friends with A.

Let's say that person A is acquainted with person B if A is friends with B or A is a friend of someone acquainted with B. 

Return the earliest time for when each person became acquainted with every other person, return -1 if there is no such earliest time.

This is used with a Union find. We want to sort the log item by their timestamp. We should model this is a graph problem and utilize a union-find data structure. Then, we loop through the events and unite each node until the number of connected components reach to 1. Notice that each time two different connected components are united the number of con [nected components decreases by 1, until it finally reaches 1. 

Here's an example: 

Input: logs = [[20190101, 0, 1], [20190104, 3, 4], [20190107, 2, 3], [20190224, 2, 4], [20190301, 0, 3], [20190312, 1, 2], [20190322, 4, 5]], N = 6

Output: 20190301

Explanation:

First even occurs where 0 and 1 become friends having [0, 1] [2] [3] [4] [5].

The second event is after 3 and 4 become friends and have [0, 1] [2] [3,4] [5]

The third event is after 2 and 3 become friends so we have [0,1] [2, 3, 4] [5]

Then 1 and 5 become friends so we have [0, 1, 5] [2, 3, 4]

Then after 0 and 3 become friends we have [0, 1, 2, 3, 4, 5], and thus all of these people.


This is a union-find function, and here are the steps: 

1. Sort the timestamp in increasing order

2. Union Element which has the same parent

3. When there is only one parent now, we are DONE.


Here's the code: 


class Solution {

    public class UF {

        int[] parent;

        int res;

        //initialize all of the people to be in different subsets corresponding to their index 

        UF(int size) {

            parent = new int[size];

            for(int i = 0; i < size; i++) {

                parent[i] = i;

            }

            res = size;

        }

        //find the child of a parent, and to do this we recurse backwards. Then, update the child or in other words "merge". 

        public int find(int child) {

            if(parent[child] != child) {

                int p = find(parent[child]);

                parent[child] = p;

            }

            return parent[child];

        }

        public void union (int a, int b) {

            //join these unions and decrement the number of groups.

            int pa = find(a);

            int pb = find(b);

            if(pa != pb) {

                parent[pb] = pa;

                res--;

            }

        }

    }



    public int earliestAcq(int[][] logs, int N) {

        //sort the arrays by date, since we are mainly measureing by TIME. 

        Arrays.sort(logs, (a, b) -> (a[0] - b[0]));

        UF uf = new UF(N);

         //union find and return when there is 1 graph left.

        for(int[] log : logs) {

            uf.union(log[1], log[2]);

            if(uf.res == 1) return log[0];

        }

        //return if there is more than 1 separate graph. 

        return -1; 

    }

}

Comments

Popular Posts