力扣【广度搜索专题】👊 547. 省份数量

650 阅读1分钟

「这是我参与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:

image.png

输入: 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 记录有多少组节点

对数组的遍历方式为:

  1. [0][0] 下标开始,从左往右,从上往下,开始遍历;
  2. 当对第 i 行遍历时,如果存在有值为 1 的坐标,例如 isConnected[i][j] = 1,如果 j 不存在于已遍历的 used 中,则将第 j 行加入到待遍历的节点;如果 j 行中同样有不存在 used 中的点,将对应的行加入到带遍历的数组中
  3. 当按照广度搜索的方式遍历完成后,count 加 1
  4. 完成上面步骤后,从第 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;
};

image.png

使用 used 快速过滤掉已经遍历过的行

考虑到这种二维数组形式的映射关系,二维数组右上和左下的对应坐标沿斜线对称,我们只需要遍历二维数组的右上或者左下部分即可