这道题目是关于邻接矩阵下图的搜索的,常见的算法是深度优先,广度优先还有拓扑排序。
这道题目我使用的深度优先进行的实现:
void searchGraph(vector<vector<int>>& M, vector<bool>& markTable, int studentId){
markTable[studentId] = true;
for(int i = 0; i < M.size(); ++i){
if(M[studentId][i] == 1 && studentId != i){ //find a friend of studentId
//search if no mark
if(!markTable[i]) searchGraph(M, markTable, i);
}
}
}
int findCircleNum(vector<vector<int>>& M) {
if(M.size() == 0) return 0;
//tag the student who has the group false -> no group , true -> exist group
vector<bool> markTable(M.size(), false);
int groupNum = 0;
for(int i = 0; i < M.size(); ++i){
if(!markTable[i]){
searchGraph(M, markTable, i);
groupNum++;
}
}
return groupNum;
}
这里我又去查阅了一下官方的解答,还有一种方法是并查集,这里我简单说一下并查集的实现,也可以去leetCode官网查看一下
并查集:简单说就是合并查询过程中的集合,遍历一个节点时,如果有其他相邻的节点那么就,让其中一个做父节点,这样如果两个节点相邻,但是他们的 “根父节点“(强调一下)不一样,那么就可以执行合并操作,合并很简单,让其中一个父节点指向另一个父节点。切记跟父节点指向-1(or anyting you like)。这样你可以直接统计-1的个数来获取组数。
下面的图是用来简单描述创建集合合并集合的过程
我对官方的java代码进行了注解,如果哪里理解不对,请看到这篇文章的大牛纠正,谢谢。
public class Solution {
int find(int parent[], int i) {//递归搜索根节点
if (parent[i] == -1)
return i;
return find(parent, parent[i]);
}
void union(int parent[], int x, int y) {//合并两个节点
int xset = find(parent, x);
int yset = find(parent, y);
if (xset != yset)
parent[xset] = yset;
}
public int findCircleNum(int[][] M) {
int[] parent = new int[M.length];
Arrays.fill(parent, -1); // 1.初始化父节点数组
for (int i = 0; i < M.length; i++) {
for (int j = 0; j < M.length; j++) {
if (M[i][j] == 1 && i != j) {
union(parent, i, j); //寻找i,j(相连)的父节点,如果不一样会在union中链接
}
}
}
int count = 0;
for (int i = 0; i < parent.length; i++) {//统计数组中根节点的数目,即组数
if (parent[i] == -1)
count++;
}
return count;
}
}
参考资料:https://leetcode-cn.com/problems/friend-circles/solution/peng-you-quan-by-leetcode/?from=groupmessage