并查集:LeetCode 547 省份数量

题目链接:LeetCode 547
题目思路:计算图中的连通分量的个数,通过深度搜索实现,或者并查集实现。

方法1 深度优先搜索

深度优先搜索,时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)

class Solution {
    public int findCircleNum(int[][] isConnected) {
        int cities = isConnected.length;
        // 记录访问过的城市下标
        boolean[] visited = new boolean[cities];
        int proviences = 0;
        for(int i = 0; i < cities; i++)
        {
            if(!visited[i])
            {
            	// 如果没访问过就对当前的下标进行染色操作
                dfs(isConnected, visited, cities, i);
                proviences++;
            }
        }
        return proviences;
    }

    public void dfs(int[][] isConnected, boolean[] visited, int cities, int i)
    {
        for(int j = 0; j < cities; j++)
        {
        	// 如果两点之间是可达的,并且j是未访问过的城市,进行递归的染色
            if(isConnected[i][j] == 1 && !visited[j])
            {
                visited[j] = true;
                dfs(isConnected, visited, cities, j);
            }
        }
    }
}

方法2 并查集

在并查集初始化的时候,每个城市都属于不同的连通分量,当两个城市之间有相连的关系时,将他们修改为同一个集合中去,进行合并,并最终统计连通分量的总数。时间复杂度 O ( n 2 l o g n ) O(n^2logn) O(n2logn),空间复杂度 O ( n ) O(n) O(n)

class Solution {
    public int findCircleNum(int[][] isConnected) {
        int cities = isConnected.length;
        int[] parent = new int[cities];
        // 并查集的初始化,认为自己是一个集合
        for(int i = 0; i < cities; i++)
            parent[i] = i;
        
        for(int i = 0; i < cities; i++)
        {
            // 避免遍历重复元素
            for(int j = i + 1; j < cities; j++)
            {
                if(isConnected[i][j] == 1)
                    union(parent, i, j);
            }
        }

        int proviences = 0;
        for(int i = 0; i < cities; i++)
        {
            if(parent[i] == i)
            {
                proviences++;
            }
        }
        return proviences;
    }


    public void union(int[] parent, int i, int j)
    {
        parent[find(parent, i)] = find(parent, j);
    }

    public int find(int[] parent, int index)
    {
        // 不是根节点的情况下
        if(parent[index] != index)
        {
            // 递归的进行路径压缩,都压缩到根节点的下边
            parent[index] = find(parent, parent[index]);
        }
        return parent[index];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值