【Warrior刷题笔记】LC1319. 连通网络的操作次数【DFS+并查集】详细注释简单易懂

题目

LC1319.连通网络的操作次数

解法一 深度优先遍历

本题实际上就是求所有主机与主机间的边所构成的图的连通分量数。任意两个连通分量间只需要一根网线就能相连,最终所求答案就是连通分量数减一。
不熟悉图和连通分量的,可以参考图与连通分量。这里我们首先使用dfs求图的连通分量数。我们使用visited数组标记遍历过的主机,防止重复遍历。从主机0开始进行遍历,若当前主机未遍历过,则连通分量数加一,同时以该主机为起点进行dfs标记该连通分量中的所有主机。遍历完成后返回连通分量数减一就是最终答案。

代码

class Solution {
public:
    int makeConnected(int n, vector<vector<int>>& connections) {
        int m = connections.size();
        if(m<n-1) return -1;
        int connectedGroupCount = 0;//连通分量数
        vector<int> visited(n,0);//主机访问标记
        vector<vector<int>> map(n,vector<int>(n,0));//图的邻接矩阵
        for(const auto& v : connections){//转化为邻接矩阵
            int a = v[0], b = v[1];
            map[a][b] = 1;
            map[b][a] = 1;
        }
        function<void(int)> dfs = [&](int pos){//dfs
            ++visited[pos];
            for(int i = 0; i < n; ++i){
                if(map[pos][i]==1 && visited[i]==0) dfs(i);
            }
        };
        for(int i = 0; i < n; ++i){
            if(visited[i]==0){//如果当前节点未遍历过
                ++connectedGroupCount;//则连通分量数加一
                dfs(i);//遍历标记该连通分量的所有节点
            }
        }
        return connectedGroupCount-1;
    }
};

复杂度分析

时间复杂度: O(m+n)m为图的边数,n为主机数。需要遍历主机和边各一次。
空间复杂度: O(n²)。因为使用了邻接矩阵辅助遍历,需要O(n²)的空间消耗。

解法二 并查集

除了深度优先遍历,我们还可以使用并查集求连通分量数。对并查集不熟悉的可以参考并查集

代码

class Solution {
    vector<int> unionFind;//并查集
public:
    int Find(int x){//查
        while(unionFind[x] != x) x = unionFind[x];//一直查找父节点
        return x;//返回祖先节点
    }

    bool Union(int x, int y){//并
        int fx = Find(x), fy = Find(y);//查找两节点的祖先节点
        if(fx != fy){//若祖先节点不同,合并两集合
            unionFind[fx] = fy;
            return true;//并返回“已合并”
        }
        return false;//否则返回“同集合”
    }

    int makeConnected(int n, vector<vector<int>>& connections) {
        int m = connections.size();//计算图的边数
        if(m<n-1) return -1;//若边数不到n-1,返回-1
        unionFind.resize(n, -1);//初始化并查集
        for(int i = 0; i < n; ++i) unionFind[i] = i;
        int connectedGroupCount = n;//初始化连通分量数为n
        for(const auto& v : connections){
            //依次遍历每条边,若合并两个连通分量,则连通分量数减一
            //若本就属于同一连通分量,则连通分量数不变
            if(Union(v[0],v[1])) --connectedGroupCount; 
        }
        return --connectedGroupCount;//返回连通分量数减一
    }
};

复杂度分析

时间复杂度: O(m*O(Union))m为图的边数。
空间复杂度: O(n)。并查集的空间消耗。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值