java并查集

最近刷leetcode接触到了并查集,在此做记录

1.介绍

并查集是一种数据结构, 常用于描述集合,经常用于解决此类问题:某个元素是否属于某个集合,或者 某个元素 和 另一个元素是否同属于一个集合。

public class UnionFind {
    private int[] id;
    private int count;

    public UnionFind(int N) { //初始化
        count = N;
        id = new int[N];
        for(int i = 0; i < N; i++) id[i] = i;
    }

    public int getCount() {
        return count;
    }

    public boolean connected(int p, int q) {//判断p、q是否同属同一个集合
        return find(p) == find(q);
    }

    public int find(int p) {
        return id[p];
    }

    public void union(int p, int q){//联合
        int pRoot = find(p);
        int qRoot = find(q);

        if(pRoot == qRoot) return;//判断是否同属一个集合

        for(int i = 0; i < id.length; i++)//p的集合被q的集合吞并掉
            if(id[i] == pRoot)  id[i] = qRoot;
        count--;
    }
}

union时间复杂度O(n) ,这样的合并操作太低效了,合并一次就O(n)。所以采用快速Union方式。

2.优化 quick-union

修改find和union
public int find(int p) {
        while(p != id[p]) p = id[p];
        return p;
}
    
public void union(int p, int q){
        int pRoot = find(p);
        int qRoot = find(q);

        if(pRoot == qRoot) return;

        id[pRoot] = qRoot;
        count--;
}

3.路径压缩加权值quick-union

public int find(int p) {
        if(p != id[p]) id[p] = find(id[p]);
        return id[p];
}

4.应用

最后提一道leetcode算法题 https://leetcode-cn.com/probl...

题目描述:给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。
只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false。 

示例 1:

输入:["a==b","b!=a"]
输出:false

解释:如果我们指定,a = 1 且 b = 1,那么可以满足第一个方程,但无法满足第二个方程。没有办法分配变量同时满足这两个方程。

示例 2:

输入:["b==a","a==b"]
输出:true

解释:我们可以指定 a = 1 且 b = 1 以满足满足这两个方程。

附上题解:

/*
路径压缩
*/

class Solution {
    public boolean equationsPossible(String[] equations) {
        int[] parent=new int[26];
        for(int i=0;i<26;i++){
            parent[i]=i;
        }
        for(String s:equations)
        {
            if(s.charAt(1)=='=')
            {
                int index1=s.charAt(0)-'a';
                int index2=s.charAt(3)-'a';
                union(parent,index1,index2);
            }
        }
        for(String s:equations)
        {   
            if(s.charAt(1)=='!')
            {
                int index1=s.charAt(0)-'a';
                int index2=s.charAt(3)-'a';
                if(find(parent,index1)==find(parent,index2)){
                    return false;
                }
            }  
        }
        return true;
    }

    public void union(int[] parent,int p,int q){//p合并q
        if(find(parent,p)!=find(parent,q)){
            parent[find(parent,q)]=parent[find(parent,p)];
        }
    }
    public int find(int[] parent,int i){
        if(parent[i]!=i){
            parent[i]=find(parent,parent[i]);//递归找到父节点
        }
        return parent[i];
    }
}

你可能感兴趣的:(java,并查集,算法-数据结构)