「这是我参与2022首次更文挑战的第 25 天,活动详情查看:2022首次更文挑战」
题目链接
547. 省份数量 - 力扣(LeetCode) (leetcode-cn.com)
题目描述
有 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
条件限制
1 <= n <= 200
n == isConnected.length
n == isConnected[i].length
isConnected[i][j] 为 1 或 0
isConnected[i][i] == 1
isConnected[i][j] == isConnected[j][i]
题目分析
题目会给我们提供一个 n*n 的矩阵,坐标 isConnected[i][j] = 1 表示 i 与 j 相连。如果多个点都是相连的,那这些点合并计算为1组,即1组里可能会有1个点,或者是有多个点。题目需要我们从给定的二维数组中计算出有多少组节点
一个合适的做法就是,使用一个 let used = new Set() 记录遍历过的点,使用 count 记录有多少组节点
对数组的遍历方式为:
- 从
[0][0]下标开始,从左往右,从上往下,开始遍历; - 当对第 i 行遍历时,如果存在有值为 1 的坐标,例如
isConnected[i][j] = 1,如果 j 不存在于已遍历的used中,则将第 j 行加入到待遍历的节点;如果 j 行中同样有不存在used中的点,将对应的行加入到带遍历的数组中 - 当按照广度搜索的方式遍历完成后,
count加 1 - 完成上面步骤后,从第
i+1行开始重复 2,3,4 步(若i+1存在used,则从下一行开始重复上述步骤
代码实现
/**
* @param {number[][]} isConnected
* @return {number}
*/
var findCircleNum = function(isConnected) {
let used = new Set();
let count = 0;
for (let i = 0; i < isConnected.length; i++) {
if (used.has(i)) {
continue;
}
count++;
let arrs = [i];
while (arrs.length > 0) {
let curr = arrs.shift();
for (let j = 0; j < isConnected[curr].length; j++) {
if (!used.has(j) && isConnected[curr][j] == 1) {
arrs.push(j);
used.add(j);
}
}
}
}
return count;
};
使用 used 快速过滤掉已经遍历过的行
考虑到这种二维数组形式的映射关系,二维数组右上和左下的对应坐标沿斜线对称,我们只需要遍历二维数组的右上或者左下部分即可