LeetCode 547. 省份数量

72 篇文章 0 订阅
547. 省份数量

难度 中等

n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。

省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。

给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。

返回矩阵中 省份 的数量。

示例 1:

img

输入:isConnected = [[1,1,0],[1,1,0],[0,0,1]]
输出:2

示例 2:

img

输入:isConnected = [[1,0,0],[0,1,0],[0,0,1]]
输出:3

提示:

  • 1 <= n <= 200
  • n == isConnected.length
  • n == isConnected[i].length
  • isConnected[i][j]10
  • isConnected[i][i] == 1
  • isConnected[i][j] == isConnected[j][i]

题解

​ 这道题也是一道经典的图论题目,就是套深搜或广搜的模板就行。除了上面两种方法,其实并查集也是一个好的解题方法。

解法一:深搜
class Solution {
    public int findCircleNum(int[][] isConnected) {
        int c = isConnected.length;//矩阵维度
        boolean[] visit = new boolean[c];//访问数组
        int count = 0;//记录变量
        for(int i = 0; i < c; i++){//行遍历
            if(!visit[i]){//该节点没有访问过
                count++;
                dfs(isConnected, visit, i);//深搜处理该节点
            }
        }
        return count;
    }

    void dfs(int[][] isConnected, boolean[] visit, int x){//深搜处理该节点
        for(int i = 0; i < isConnected[0].length; i++){
            if(isConnected[x][i] == 1 && !visit[i]){//遍历相邻节点
                visit[i] = true;//把相邻节点置为访问节点
                dfs(isConnected, visit, i);//深搜处理该节点
            }
        }
    }
}
解法二:广搜
class Solution {
    public int findCircleNum(int[][] isConnected) {
        int r = isConnected.length;//矩阵维度
        int count = 0;//记录变量
        boolean[] visit = new boolean[r];//该节点是否遍历过
         Queue<Integer> queue = new LinkedList<Integer>();//广搜辅助队列
        for(int i = 0; i < r; i++){
            if(!visit[i]){//没有遍历过
                count++;
                queue.offer(i);//入队
                while(!queue.isEmpty()){//队列不为空
                    int j = queue.poll();//出队
                    visit[j] = true;//置为true
                    for(int k = 0; k < r; k++){
                        if(isConnected[j][k] == 1 && !visit[k]){//遍历相连节点
                            queue.offer(k);
                        }
                    }
                }
            }
        }
        return count;
    }
}
解法三:并查集

​ 并查集在有些图相关问题上也是可解的,比如这道题是寻找省份数量,就是有多少个集合,通过并查集也可以去解题。也建议大家学一下并查集的模板,大概即使一个步骤:

  • 初始化父节点为本身
  • 寻找父节点
  • 合并父节点
  • 判断集合数量
class Solution {
    public int findCircleNum(int[][] isConnected) {
        int c = isConnected.length;//矩阵维度
        int[] parent = new int[c];//父节点数组
        
        for(int i = 0; i < c; i++){//1、初始化父节点为本身
            parent[i] = i;
        }

        for(int i = 0; i < c; i++){//行遍历
            for(int j = i + 1; j < c; j++){//列遍历
                if(isConnected[i][j] == 1){//相连
                    union(parent, i, j);//合并父节点
                }
            }
        }

        int count = 0;
        for(int i = 0; i < c; i++){//4、判断集合数量
            if(parent[i] == i){//每个集合只有一个根节点,如果父节点等于本身,就代表一个集合
                count++;
            }
        }

        return count;
    }

    int find(int[] parent, int x){//2、寻找父节点
        return x == parent[x] ? x : find(parent, parent[x]);
    }

    void union(int[] parent, int index1, int index2){//3、合并父节点
        parent[find(parent, index1)] = find(parent, index2);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值