并查集专题

参考:分享丨【算法题单】常用数据结构(前缀和/栈/队列/堆/字典树/并查集/树状数组/线段树)- 讨论 - 力扣(LeetCode)

板子:

class UnionFind {
    vector<int> fa; // 代表元
    vector<int> sz; // 集合大小

public:
    int cc; // 连通块个数

    UnionFind(int n) : fa(n), sz(n, 1), cc(n) {
        // 一开始有 n 个集合 {0}, {1}, ..., {n-1}
        // 集合 i 的代表元是自己,大小为 1
        ranges::iota(fa, 0); // iota(fa.begin(), fa.end(), 0);
    }

    // 返回 x 所在集合的代表元
    // 同时做路径压缩,也就是把 x 所在集合中的所有元素的 fa 都改成代表元
    int find(int x) {
        // 如果 fa[x] == x,则表示 x 是代表元
        if (fa[x] != x) 
            fa[x] = find(fa[x]); // fa 改成代表元
        return fa[x];
    }

    // 判断 x 和 y 是否在同一个集合
    bool is_same(int x, int y) {
        // 如果 x 的代表元和 y 的代表元相同,那么 x 和 y 就在同一个集合
        // 这就是代表元的作用:用来快速判断两个元素是否在同一个集合
        return find(x) == find(y);
    }

    // 把 from 所在集合合并到 to 所在集合中
    // 返回是否合并成功
    bool merge(int from, int to) {
        int x = find(from), y = find(to);
        if (x == y) { // from 和 to 在同一个集合,不做合并
            return false;
        }
        fa[x] = y; // 合并集合。修改后就可以认为 from 和 to 在同一个集合了
        sz[y] += sz[x]; // 更新集合大小(注意集合大小保存在代表元上)
        // 无需更新 sz[x],因为我们不用 sz[x] 而是用 sz[find(x)] 获取集合大小,但 find(x) == y,我们不会再访问 sz[x]
        cc--; // 成功合并,连通块个数减一
        return true;
    }

    // 返回 x 所在集合的大小
    int get_size(int x) {
        return sz[find(x)]; // 集合大小保存在代表元上
    }
};

一、基础

二、进阶

Leetcode 1061. 按字典序排列最小的等效字符串

思路:dfs或者并查集

Code:

class Solution {
public:
    string smallestEquivalentString(string s1, string s2, string baseStr) {
        int fa[26];
        // 初始化
        for (int i = 0; i < 26; i ++)   fa[i] = i;
        // func:查询x的父节点
        auto find = [&] (this auto&& find, int x) -> int {
            if (fa[x] != x) fa[x] = find(fa[x]);
            return fa[x];  
        };
        // func:把大的指向小的
        auto merge = [&](int x, int y) {
            auto [small, big] = minmax(find(x), find(y));
            fa[big] = small;
        };
        for (int i = 0; i < s1.size(); i ++)    merge(s1[i] - 'a', s2[i] - 'a');
        for (int i = 0; i < baseStr.size(); i ++)
            baseStr[i] = find(baseStr[i] - 'a') + 'a';
        return baseStr;
    };
};

 

三、GCD 并查集

四、数组上的并查集

五、区间并查集

六、边权并查集

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Ocean__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值