How Big Is Your Friend Group

Solve this Problem
Medium30–35 min
Topics
Companies

People start out alone, and friendships merge groups. You receive a list of operations: "merge the groups of a and b", or "how big is the group of a?". Answer every operation in order with the size of the group of a (after the merge, for merge operations).

A disjoint set (union-find) stores the group sizes at the roots of trees. Union by size hooks the smaller tree under the larger one, which keeps the trees shallow.

Test Case 1:

Input:n = 6, ops = [[1,0,1],[1,2,3],[2,3,0],[1,1,3],[2,2,0],[1,4,5],[2,4,0],[1,0,5]]
Output:[2,2,2,4,4,2,2,6]
Explanation:Merging 0–1 gives a group of 2, merging 2–3 another; asking about 3 gives 2; merging 1 and 3 makes a group of 4 (asking about 2 gives 4); 4–5 make a group of 2 (asking about 4 gives 2); the last merge 0–5 joins the groups of 4 and 2 into one of 6. As an adjacency list the friendships are 0–1, 2–3, 1–3, 4–5, 0–5.

Test Case 2:

Input:n = 3, ops = [[1,1,1],[2,2,0]]
Output:[1,1]
Explanation:Merging a person with themselves changes nothing.

Test Case 3:

Input:n = 1, ops = [[2,0,0]]
Output:[1]
Explanation:A single person is a group of size 1.

Constraints

  • ◆1 ≤ n ≤ 10 people numbered 0 … n-1; at the start every person is alone in their own group
  • ◆ops is a list of at most 12 operations, each a row [kind, a, b] with 0 ≤ a, b < n: kind 1 means "merge the groups of a and b" (nothing changes if they are already together), kind 2 means "ask for the size of the group of a" (b is ignored)
  • ◆The operations are processed in the given order and every operation produces one answer
  • ◆Return the answers: for a question the size of the group of a; for a merge the size of the group of a AFTER the merge
🚀

Try the Dry Run

Don't just read the solution — watch it execute, one step at a time.

Approach & Solutions

Brute Force — Keep Group Labels and Count the Members

Brute

Keep a group label per person (at first their own number). To merge a and b when their labels differ, sweep over all people and give everyone with b's label the label of a. To report a size, count how many people carry a's label. Both merging and counting sweep all n people, so every operation costs O(n).

TimeO(n) per operation
SpaceO(n)
1class Solution { 2 public int[] groupSizes(int n, int[][] ops) { 3 int[] label = new int[n]; 4 for (int i = 0; i < n; i++) label[i] = i; 5 int[] answers = new int[ops.length]; 6 for (int k = 0; k < ops.length; k++) { 7 int a = ops[k][1], b = ops[k][2]; 8 if (ops[k][0] == 1 && label[a] != label[b]) { 9 int from = label[b], to = label[a]; 10 for (int i = 0; i < n; i++) { 11 if (label[i] == from) label[i] = to; 12 } 13 } 14 int size = 0; 15 for (int i = 0; i < n; i++) { 16 if (label[i] == label[a]) size++; 17 } 18 answers[k] = size; 19 } 20 return answers; 21 } 22}

Optimal — Disjoint Set With Union by Size and Path Compression

Optimal

Keep every group as a tree with parent[] pointers towards the root, and store the number of people in each tree at its root (size[]). find(x) walks up to the root, shortening the path as it goes (path compression). To merge, hook the root of the SMALLER group under the root of the LARGER group and add the sizes; making the big tree the root keeps trees shallow. The size of a person's group is size[find(x)], so each operation takes nearly constant time.

TimeO(α(n)) per operation
SpaceO(n)
1class Solution { 2 private int find(int[] parent, int x) { 3 while (parent[x] != x) { 4 parent[x] = parent[parent[x]]; 5 x = parent[x]; 6 } 7 return x; 8 } 9 10 public int[] groupSizes(int n, int[][] ops) { 11 int[] parent = new int[n]; 12 int[] size = new int[n]; 13 for (int i = 0; i < n; i++) { 14 parent[i] = i; 15 size[i] = 1; 16 } 17 int[] answers = new int[ops.length]; 18 for (int k = 0; k < ops.length; k++) { 19 int ra = find(parent, ops[k][1]); 20 if (ops[k][0] == 1) { 21 int rb = find(parent, ops[k][2]); 22 if (ra != rb) { 23 if (size[ra] < size[rb]) { 24 int tmp = ra; 25 ra = rb; 26 rb = tmp; 27 } 28 parent[rb] = ra; 29 size[ra] += size[rb]; 30 } 31 } 32 answers[k] = size[ra]; 33 } 34 return answers; 35 } 36}

Related Problems