携手创作,共同成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情
省份数量
有
n
个城市,其中一些彼此相连,另一些没有相连。如果城市a
与城市b
直接相连,且城市b
与城市c
直接相连,那么城市a
与城市c
间接相连。省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。给你一个n x n
的矩阵isConnected
,其中isConnected[i][j] = 1
表示第i
个城市和第j
个城市直接相连,而isConnected[i][j] = 0
表示二者不直接相连。返回矩阵中 省份 的数量。
分析
- 把城市与城市相连的情况看作是图,城市是图的节点,相连关系是图的边,所以给出的二维矩阵可以看作是图的邻接矩阵,省份个数就是图的联通分量,所以要求省份的数量就是求邻接矩阵对应的图的连通分量
- 简单介绍一下图,邻接矩阵和连通分量
- 图是树结构的延伸,树只能有一个根节点,图是没有这个限制的,节点自由组合相连形成,图分有向图和无向图,本题因为没有特殊说明a和b相连,b和a不相连,那就可以默认是无向图。那要怎么来表示一个图的节点和边呢?使用一个二维矩阵,表示两个点之间的关系,本题中规定的是如果相连就是1,不相连为0,因此通过给出一个邻接矩阵就可以还原图的结构。题目中提示省份是一组直接或间接相连的城市,没有不相连的城市,求省份的数量,即图中任意两个顶点之间是否有路径可达,这个概念就是无向图的极大连通子图,也就是连通分量,因此这道题分析之后,简单来说就是给出了一个邻接矩阵去找这个图的连通分量
- 关于获取连通分量
- 可以DFS,BFS或者并查集,并查集是很优雅的方式但是需要自己构造,这里用常见的DFS来解答
- 关于优化
- 在搜索的时候一般都是记忆化搜索,之前的几篇代码笔记中使用Map的次数比较多,这次改成Set
代码
function findCircleNum(M) {
const visited = new Set();
let circles = 0;
for (let i = 0; i < M.length; i++) {
if (!visited.has(i)) {
dfs(i);
circles++;
}
}
return circles;
function dfs(i) {
for (let j = 0; j < M.length; j++) {
if (M[i][j] === 1 && !visited.has(j)) {
visited.add(j);
dfs(j);
}
}
}
}
总结
- 描述的比较多,为了概念的正确性,描述的甚至有点啰嗦,比如对于省份的解释,在遇到这种题的时候,还是比较偏向审题2小时代码5分钟,如果对图的算法有一定敏感性,在读完题后可能就可以联想到联通量这个知识点
- 今天也是有收获的一天