题目描述链接:https://leetcode-cn.com/problems/friend-circles/
解题思路:基本思想采用DFS的方法进行深搜。用一个访问来记录每个节点是否被访问,从头节点开始深度优先搜索朋友。每进行以此搜索,就会把开始节点所属的朋友圈全部人员标记完成。
然后再主函数找到未被搜索的节点,继续深搜即可。记录主函数调用深搜函数的次数就是朋友圈的个数。
另外记录一下自己在解这道题过程中犯过的错误。开始时候自己以为这是上三角矩阵,那么直接对上三角矩阵进行搜索就好了,结果就是出现了错误答案,通过分析总结原因如下:
这里用例子来说明:如有一个四阶矩阵,表示朋友关系分别为[0,3],[1,2],[2,3],如果用上三角矩阵的话,第一次搜索会将0,3标记,但由于是上三角则对3的朋友进行搜索时不会再搜到2了(3>2,在矩阵的第四行搜索只能从第四列开始,而第四列后面没有元素,则表示第三行搜索结束)。导致再从1开始搜索,将[1,2],和[2,3]搜索到,最终答案为2而不是应该的正确答案1。
所以每次递归搜索的时候都应该从行的第一个元素开始搜索。但修改之后出现了栈溢出的问题,即递归无法退出了,一直搜下去了。分析原因为:由于是对称矩阵会陷入死递归(即无穷的递归自身的调用),比如:如果M[0][3]=1,接下来我们就会对M[3]这一行进行搜索而M[3][0]=M[0][3]=1,就会再对0行进行搜索,0行又会到3行进行搜索,这样递归就无法退出了。解决方法就是再对其进行搜索之前判断其是否已经被标记,如果已经被标记过了,说明改节点的朋友已经全部找到了,没有必要对改节点列号对应的行进行搜索了:
采用DFS实现的LeetCode代码如下:
class Solution { public: bool vis[205]; int ans; int findCircleNum(vector<vector<int>>& M) { int len=M[0].size(); for(int i=0;i<len;++i){ if(!vis[i]){ dfs(i,M); ans++; } } return ans; } void dfs(int start,vector<vector<int>> M){ if(start==M[start].size()){ return ; } int j; for(j=0;j<M[start].size();j++){ if(M[start][j]==1){ if(vis[j]!=1){ vis[j]=1; dfs(j,M); } } } } };