并查集(UnionFindSet)
也叫做不相交集合(Disjoint Set)
两个核心操作
- 查找(Find):查找元素所在的集合(指广义的数据集合)
- 合并(Union):将两个元素所在的集合合并为一个集合
两种常见速录
- Quick Find 查找(Find) 时间复杂度:O(1) 合并(Union) 时间复杂度:O(n)
- Quick Union 查找(Find) 时间复杂度:O(logn) 合并(Union) 时间复杂度:O(logn)
核心代码
/**
 * 并查集节点
 */
export class UnionFindSetNode<T> {
    /** 所引用得节点数 */
    size = 1;
    /** 父节点 */
    parent: UnionFindSetNode<T> = this;
    constructor(public val: T) {}
}
export class UnionFindSet<T> {
    private _size = 0;
    /** 包含的集合数 */
    get size() {
        return this._size;
    }
    /** 集合储存 */
    map = new Map<T, UnionFindSetNode<T>>();
    /** 添加新节点 */
    add(val: T) {
        if (this.map.has(val)) return;
        this.map.set(val, new UnionFindSetNode(val));
        this._size++;
    }
    /** 比较两个节点是否属于同一节点 */
    same(val1: T, val2: T) {
        const root1 = this.find(val1);
        const root2 = this.find(val2);
        return root1 && root2 ? root1 === root2 : false;
    }
    /** 查找节点的根节点 */
    find(val: T): T | null {
        return this.findRoot(val)?.val ?? null;
    }
    /** 合并两个节点 */
    union(val1: T, val2: T) {
        let root1: UnionFindSetNode<T> = this.findRoot(val1)!;
        let root2: UnionFindSetNode<T> = this.findRoot(val2)!;
        if (!root1 || !root2 || root1 === root2) return;
        this._size--;
        if (root1.size < root2.size) [root1, root2] = [root2, root1];
        root2.parent = root1;
        root1.size += root2.size;
        root2.size = 1;
    }
    private findRoot(val: T): UnionFindSetNode<T> | null {
        let node: UnionFindSetNode<T> = this.map.get(val)!;
        if (!node) return null;
        while (node.parent !== node) {
            node.parent = node.parent.parent;
            node = node.parent;
        }
        return node;
    }
}