力扣547.省份数量问题解法---并查集

并查集学了忘,忘了学,再学再忘,干脆写成博客,忘了就回来回顾一下。

并查集主要用于解决一些元素分组的问题。它管理一系列不相交的集合,并支持两种操作:

  • 合并(Merge):把两个不相交的集合合并为一个集合。
  • 查询(Find):查询两个元素是否在同一个集合中

初始化: 一开始所有节点都是独立的个体,自己是自己的父亲

int fa[MAXN];
inline void init(int n)
{
    for (int i = 1; i <= n; ++i)
        fa[i] = i;
}

查询:按照连接链条查上去就可以找到父亲

int find(int x)
{
    if(x == fa[x])
        return x;
    else{
        fa[x] = find(fa[x]);  //父节点设为根节点
        return fa[x];         //返回父节点
    }
}

合并:两个集合合并,也可以看作是两棵树的根节点连在一起就可以了

inline void merge(int i, int j)
{
    fa[find(i)] = find(j);
}

并查集关键点就在于上述的两个函数,其中在查找函数中我们注意到有一条指令是

fa[x] = find(fa[x]);

这条指令是优化并查集的关键,如果没有这句话,那么因为合并的原因,在极端情况下集合的形状会变为一个链条,查询效率底下。

⚠并查集参考:算法学习笔记(1) : 并查集 - 知乎 (zhihu.com)

⬆⬆⬆这篇文章详细的介绍了并查集,图文并茂的形式慢慢引导我们从合并变为链条到后面慢慢的优化压缩路径,看完这篇会对大家帮助很大!

回过头看这道题:

 非常经典的并查集题目,只需要遍历一遍分好集合,记录连通分量个数即可

class Solution {
public:
    int fa[201];
    int findCircleNum(vector<vector<int>>& isConnected) {
        for(int i = 0; i < 201; i++){
            fa[i] = i;
        }
        int n = isConnected.size();
        for(int i = 0; i < n; i++){
            for(int j = i; j < n; j++){
                if(isConnected[i][j] == 1){
                    merge(i,j);
                }
            }
        }
        int ans = 0;
        for(int i = 0; i < n; i++){
            if(fa[i] == i){
                ans++;
            }
        }
        return ans;

    }
    int find(int x){
        if(fa[x] == x) return x;
        fa[x] = find(fa[x]);
        return fa[x];
    }
    void merge(int x, int y){
        fa[find(x)] = find(y);
    }
};

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值