summary:
classic algrithm for union find
package com.odyssey.app.algorithm.lc.unionfind;
/**
*
* 547
* medium
* https://leetcode.com/problems/friend-circles/
*
* There are N students in a class. Some of them are friends, while some are not. Their friendship is transitive in nature. For example, if A is a direct friend of B, and B is a direct friend of C, then A is an indirect friend of C. And we defined a friend circle is a group of students who are direct or indirect friends.
*
* Given a N*N matrix M representing the friend relationship between students in the class. If M[i][j] = 1, then the ith and jth students are direct friends with each other, otherwise not. And you have to output the total number of friend circles among all the students.
*
* Example 1:
* Input:
* [[1,1,0],
* [1,1,0],
* [0,0,1]]
* Output: 2
* Explanation:The 0th and 1st students are direct friends, so they are in a friend circle.
* The 2nd student himself is in a friend circle. So return 2.
* Example 2:
* Input:
* [[1,1,0],
* [1,1,1],
* [0,1,1]]
* Output: 1
* Explanation:The 0th and 1st students are direct friends, the 1st and 2nd students are direct friends,
* so the 0th and 2nd students are indirect friends. All of them are in the same friend circle, so return 1.
* Note:
* N is in range [1,200].
* M[i][i] = 1 for all students.
* If M[i][j] = 1, then M[j][i] = 1.
*
* @author Dingsheng Huang
* @date 2020/3/31 1:27
*/
public class FriendCircles {
class UnionFind {
int count;
int[] id;
int[] rank;
private void init(int peopleCount) {
id = new int[peopleCount];
rank = new int[peopleCount];
for (int i = 0; i < peopleCount; i++) {
id[i] = i;
rank[i] = 1;
count++;
}
}
private int find(int p) {
while (p != id[p]) {
p = id[p];
}
return p;
}
private void union(int p, int q) {
int pRoot = find(p);
int qRoot = find(q);
if (pRoot == qRoot) {
return;
}
if (rank[pRoot] > rank[qRoot]) {
id[qRoot] = pRoot;
rank[pRoot] += rank[qRoot];
} else {
id[pRoot] = qRoot;
rank[qRoot] += rank[pRoot];
}
count--;
}
}
public int findCircleNum(int[][] M) {
int peopleCount = M.length;
UnionFind unionFind = new UnionFind();
unionFind.init(peopleCount);
for (int i = 0; i < peopleCount; i++) {
for (int j = i; j < peopleCount; j++) {
if (M[i][j] == 1) {
unionFind.union(i, j);
}
}
}
return unionFind.count;
}
}