union-Find

class UF{
    int count;
    int[] parent;
    int[] size;
    public UF(int n){
        this.count = n;
        parent = size = new int[n];
        for(int i=0; i<n; i++){
            parent[i] = i;
            size[i] = 1;
        }
    }


    public void union(int p ,int q){
        int rootP = find(p);
        int rootQ = find(q);
        if(rootP == rootQ) return;
        
        if(size[rootP] >size[rootQ]){
            parent[Q] = rootP;
            size[rootP] +=size[rootQ]
        }else(
            parent[P] = rootQ;
            size[rootQ] += size[rootP];
        }
        count --;
    }

    public connect(int p,int q){
        return find(p) == find(q);
    }
        
    //返回x的根结点
    private int find(int x){
        while(x != parent[x]){
            //路径压缩
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }
}
  1. 用parent数组记录每一个节点的父节点,相当于指向父节点
  2. size记录每棵树的重量,目的让union后拥有平衡性
  3. find函数进行路径压缩,使得union和connect时间复杂度为O(1)

很多使用DFS深度有限算法的问题也可以用Union-Find算法解决

装着若干字符串表示的算式的数组equations,每个算式equations[i]长度都是4,只有两种情况

a==b or a!=b,其中a,b可以是任意小写字母

若所有算式都不会互相冲突,返回true,否则返回false

动态连通性是一种等价关系,具有自反性,传递性,对称性

boolean equationsPossible(String[] equations){
    //26个英文字母
    Uf uf = new Uf(26);
    for(String eq: equations){
        if(eq.charAt(1) == '='){
            char x = eq.charAt(0);
            char y = eq.charAt(3);
            uf.union(x - 'a',y-'a');
        }
    }
    //检查不等关系是否打破相等关系
    for(String eq: equations){
        if(eq.charAt(1) == '1'){
            char x = eq.charAt(0);
            char y = eq.charAt(3);
            if(uf.connected(x-'a',y-'a') return false;        
        }
    }
    return ture;
}

private void union(int p, int q){
    int pRoot = find(p);
    int qRoot = find(q);
    if(size[pRoot]>size[qRoot]){
        parent[qRoot] = pRoot;
        size[pRoot] += size[qRoot];
    }else{
        size[qRoot] += size[pRoot];
        parent[pRoot] = qRoot;
    }
}

boolean connected(int p, int q){
    int rootP = find(p);
    int rootQ = find(q);
    return rootP == rootQ;
}

int find(int x){
    while(parent[x] != x){
        parent[x] = parent[parent[x]];
        x = parent[x];
    }
    return x;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值