leetcode990并查集问题

并查集

并查集,用于判断一对元素之间是否相连,他们之间是否相连是动态添加的,这一类问题叫做动态连通性问题。主要执行的操作是
1、合并
2、判断是否处于同一个集合中
并查集使用哈希表或者数组实现存储的元素用于表示 当前结点 指向的 根结点,初始化的时候根结点指向自己。

合并操作就是把 一个集合的根结点指向另一个集合的根结点,两个元素的根结点一样则代表元素 处于同一个集合之中。
这种表示 不相交集合的方法称之为 代表元法,每个结点的根结点作为一个集合的代表元

并查集:最常见的使用就是kruskal最小生成树算法。也就意味着你首先要知道你的顶点的个数

并查集常见的优化方案
1、路径压缩(隔代压缩、完全压缩)
2、按秩合并

下面展示一道经典并查集例题
输入:[“a==b”,“b!=a”]
输出:false
解释:如果我们指定,a = 1 且 b = 1,那么可以满足第一个方程,但无法满足第二个方程。没有办法分配变量同时满足这两个方程。

以下代码是leetcode官方题解,我只是加上了个人注释方便理解

class Solution {
    public boolean equationsPossible(String[] equations) {
        /**
         * 1、初始化并查集
         * 确定顶点个数,a-z为26个字符
         * 根结点初始为本身,将26个字符按照顺序编程数字方便对比
         */
        int parents[] = new int[26];
        for(int i=0;i<26;i++){
            parents[i]=i;
        }
        //2、遍历 进行等价合并操作
        for(String s:equations){
            if(s.charAt(1)=='='){
                int index1 = s.charAt(0)-'a';
                int index2 = s.charAt(3)-'a';
                union(parents,index1,index2);  //合并
            }
        }
        //3、对比 验证是否存在矛盾
        for(String s:equations){
            if(s.charAt(1)=='!'){
                int index1 = s.charAt(0)-'a';
                int index2 = s.charAt(3)-'a';
                //注意此处是 a!=b 则若两者拥有相同的根结点则说明两者在同一集合中矛盾
                if(find(parents,index1) == find(parents,index2))
                    return false;
            }
        }
        return true;
    }
    //合并
    public void union(int[] parents,int index1,int index2){
        /**
		 * find(parent, index1)    找到index1对应的根结点
		 * find(parent, index2)    找到index2对应的根结点
		 * 合并
		 * 其中parent[i]存放的是该结点的根结点 , i则代表了该结点是第几个结点
		 */
        parents[find(parents,index1)] = find(parents,index2);
    }
    //查询根结点, 并进行路径压缩(这里采用的完全压缩)
    //根结点 数组下标必对应数组元素
    public int find(int[] parents,int index){
        while(parents[index]!=index){
            parents[index] = parents[parents[index]];
            index = parents[index];
        }
        return index;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值