该问题与前面的200题岛屿数量类似,可以使用深度优先搜索,广度优先搜索,并查集解决
并查集的实现代码入下:
public class UnionFind {
private int count;
private int[] parent;
public UnionFind(int n) {
count = n;
parent = new int[n];
for(int i=0; i<n; i++) {
parent[i] = i;
}
}
/**
* 查找p所在集合的代表,代表的下标和存的值是相同的即parent[index]==index
* @param p
* @return
*/
public int find(int p) {
while(p!=parent[p]) {
p = parent[p];
}
return p;
}
/**
* 合并两个集合
* @param p
* @param q
*/
public void union(int p, int q) {
int rootP = find(p);
int rootQ = find(q);
if(rootP != rootQ) {
parent[rootP] = rootQ;
count--;
}
}
public int getCount() {
return count;
}
}
并查集的三个基本操作:
makeSet(s):建立一个新的并查集,其中包含s个单元素集合
unionSet(x, y):把元素x和元素y所在的集合合并,要求x和y所在的集合不相交,如果相交则不合并
find(x):找到元素x所在的集合的代表
使用并查集的解法如下:
public int findCircleNum(int[][] M) {
UnionFind unionFind = new UnionFind(M.length);
for (int i = 0; i < M.length; i++) {
for (int j = 0; j < M[0].length; j++) {
if (M[i][j] == 1)
unionFind.union(i, j);
}
}
return unionFind.getCount();
}