链接
题目:
方法一:dfs
使用邻接矩阵记录图,注意和邻接表在遍历时不一样;
当没有被marked[ ] 标记时,才进行记数,并dfs ,和岛屿问题类似;
所求未连通的组数,所以r++在main中记录,而不是在dfs中;
class Solution {
boolean[] marked;
public int findCircleNum(int[][] isConnected) { // 邻接矩阵
int n=isConnected.length; //对称的,只需要 n
// 标记
marked=new boolean[n];
int r=0;
for(int i=0;i<n;i++){
// 若当前顶点未被访问过,就是新的连通域,才记数 ! 再dfs 类似岛屿问题
if(marked[i]==false){ // 未被标记过的才作为顶点;
r++;
dfs(isConnected,i); //从 i 出发!
}
}
return r;
}
void dfs(int[][] isConnected,int s){
if(marked[s]){
return;
}
// 继续遍历顶点 s 与之相邻的点, 和邻接表不一样 !!!
for(int i=0;i<isConnected.length;i++){
// 选择
// 标记和S连通的节点
marked[s]=true;
// dfs(如果和当前顶点连通)
if(isConnected[s][i]==1){ //isConnected[s][i]即从s和i相连,所以dfs再从 i 出发;
dfs(isConnected,i);
}
}
}
}
方法二:并查集
class Solution {
public int findCircleNum(int[][] isConnected) {
int n = isConnected.length;
// 初始化并查集
UnionFind uf = new UnionFind(n);
// 遍历每个顶点,将当前顶点与其邻接点进行合并
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (isConnected[i][j] == 1) {
uf.union(i, j);
}
}
}
// 返回最终合并后的集合的数量
return uf.size;
}
}
// 并查集
class UnionFind {
int[] roots;
int size; // 集合数量
public UnionFind(int n) {
roots = new int[n];
for (int i = 0; i < n; i++) {
roots[i] = i;
}
size = n;
}
public int find(int i) {
if (i == roots[i]) {
return i;
}
return roots[i] = find(roots[i]);
}
public void union(int p, int q) {
int pRoot = find(p);
int qRoot = find(q);
if (pRoot != qRoot) {
roots[pRoot] = qRoot;
size--;
}
}
}