题目:省份数量
有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。
省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。
给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。
返回矩阵中 省份 的数量。
示例 1:
输入: isConnected = [[1,1,0],[1,1,0],[0,0,1]]
输出: 2
示例 2:
输入: isConnected = [[1,0,0],[0,1,0],[0,0,1]]
输出: 3
提示:
1 <= n <= 200n == isConnected.lengthn == isConnected[i].lengthisConnected[i][j]为1或0isConnected[i][i] == 1isConnected[i][j] == isConnected[j][i]
解题思路
- 从题目描述来看,显然这是一个使用邻接矩阵表示的图,图中结点就是编号从0到M的学生,所谓的朋友圈就是一个连通子图。所以问题就变为在无向图中找连通子图的数量。
- 使用 boolean[] marked = new boolean[n];表示结点的访问情况,int count计数连通子图的数量。
- 定义void dfs2(int[][] M, int v, boolean[] marked),使用深度优先访问连通子图的所有结点。
- 遍历所有结点[0, n - 1],如果节点没有被访问过,且两个结点之间有边连接(M[i][j] = 1,表示已知第i个和j个学生互为朋友关系),就将该结点表示为已访问marked[i] = true;,然后递归地调用。
- 主函数遍历所有结点[0, n - 1],每当发现没有被访问的结点,说明这是一个新的连通子图。所以count++,然后将该结点设置为已访问,调用 dfs2(M, i, marked);。这个调用就可以将包括该结点的连通子图中所有结点都访问到。
代码实现
public int findCircleNum(int[][] M) {
int count = 0;
n = M.length;
boolean[] marked = new boolean[n];
for (int i = 0; i < n; i++) {
if (!marked[i]) {
count++;
marked[i] = true;
dfs2(M, i, marked);
}
}
return count;
}
private void dfs2(int[][] M, int v, boolean[] marked) {
for (int i = 0; i < n; i++) {
if (!marked[i] && M[v][i] == 1) {
marked[i] = true;
dfs2(M, i, marked);
}
}
}
运行结果
复杂度分析
- 空间复杂度:O(n)
- 时间复杂度:O(n^2)
在掘金(JUEJIN) 一起分享知识, Keep Learning!