Understand what the interviewer is asking for by using test cases and questions about the problem.
- Established a set (2-3) of test cases to verify their own solution later.
- Established a set (1-2) of edge cases to verify their solution handles complexities.
- Have fully understood the problem and have no clarifying questions.
- Have you verified any Time/Space Constraints for this problem?
HAPPY CASE
Input: logs = [[20190101,0,1],[20190104,3,4],[20190107,2,3],[20190211,1,5],[20190224,2,4],[20190301,0,3],[20190312,1,2],[20190322,4,5]], n = 6
Output: 20190301
Input: logs = [[0,2,0],[1,0,1],[3,0,3],[4,1,2],[7,3,1]], n = 4
Output: 3
EDGE CASE
Input: logs = [[1,0,1],[20190104,3,4],[20190107,2,3],[20190211,1,5],[20190224,2,4],[20190301,0,3],[20190312,1,2],[0,4,5]], n = 10
Output: -1
Match what this problem looks like to known categories of problems, e.g. Linked List or Dynamic Programming, and strategies or patterns in those categories.
For graph problems, we want to consider the following approaches:
Plan the solution with appropriate visualizations and pseudocode.
General Idea: Use union find to join two groups and reduce the group of friends by 1. At the end we will have only 1 friend group meaning everyone is friends with everyone.
1. Initialize a variable time, which stores the value of the current timestamp of the DSU.
2. Traverse the given array, and perform union operation between and update the current timestamp to time if belong to the different sets.
3. If the total number of sets after completely traversing through the array is 1, return the value of the variable time, else return -1.
⚠️ Common Mistakes
You can think of the node "representing" the connected component as sometimes further (a certain number of edges) away. A common mistake is not seeing that the parent is closer. To ensure best runtime, the smaller connected component is merged into the larger one.
Implement the code to solve the algorithm.
class Solution:
def earliestAcq(self, logs: List[List[int]], n: int) -> int:
# sort the events in chronological order
logs.sort(key = lambda x: x[0])
uf = UnionFind(n)
# treat each individual as a separate group
group_cnt = n
# merge the groups as we traverse the logs
for timestamp, friend_a, friend_b in logs:
if uf.union(friend_a, friend_b):
group_cnt -= 1
# return timestamp when individuals are connected to each other
if group_cnt == 1:
return timestamp
# not everyone is connected
return -1
class Solution {
public int earliestAcq(int[][] logs, int n) {
// sort the events in chronological order
Arrays.sort(logs, new Comparator<int[]>() {
public int compare(int[] log1, int[] log2) {
Integer tsp1 = new Integer(log1[0]);
Integer tsp2 = new Integer(log2[0]);
return tsp1.compareTo(tsp2);
}
});
// treat each individual as a separate group
int groupCount = n;
UnionFind uf = new UnionFind(n);
for (int[] log : logs) {
int timestamp = log[0];
int friendA = log[1];
int friendB = log[2];
// merge the groups
if (uf.union(friendA, friendB)) {
groupCount -= 1;
}
// return timestamp when individuals are connected to each other
if (groupCount == 1) {
return timestamp;
}
}
// not everyone is connected
return -1;
}
}
Review the code by running specific example(s) and recording values (watchlist) of your code's variables along the way.
Evaluate the performance of your algorithm and state any strong/weak or future potential work.
Let E be the number of edges or the number of timestamps. Let V be the number of vertices or the number of people.