并查集——LeetCode-990.等式方程的可满足性

这里是题目描述:LeetCode-990.等式方程的可满足性

本题使用并查集来解,难度并不大,大体方法是:首先遍历题目给出的字符串数组equations建立并查集,如果遍历到的字符串包含"==",则对"=="两边的字符建立并查集,如果两个字符均没有包含在一个集合中,则新建立一个集合包含它们;如果两个字符只有一个包含在某个集合中或两个字符分别在不同的集合中,则将它们合并入一个集合中;如果两个字符位于同一个集合中,则不用进行任何操作 。位于同一个集合中的元素意味着它们被赋了相等的值,它们两两之间"=="成立。建立完并查集,再次遍历equations来检查方程组是否成立,如果遍历到的字符串包含"!=",则检查字符串中包含的两个字符是否位于同一个集合中,如果位于一个集合,或者"!="两边的两字符相等,则和之前构建的并查集矛盾,返回false。如果遍历完所有包含!=的字符串都没有返回false,则证明方程组中的所有等式合法,返回true

建立并查集的方法是:

  • 使用哈希表和存储所有集合,哈希表的键值设定为int类型,作为一个集合的root节点;哈希表的每个键值对应一个集合Set,存储这个集合中包含的所有字符(方程组中所有相互满足"=="的字符)
  • 建立数组存储每个字符所在集合的root节点的值,初始化为0代表还没有被存入一个集合
  • 并查集中集合的新建、存入新字符、合并两个集合、查询一个字符所在的集合等基本操作这里不再介绍,详见下面的题解代码
    在这里插入图片描述
    题解代码:
class Solution {
    //并查集问题
    public boolean equationsPossible(String[] equations) {
        HashMap<Integer,HashSet<Character>> unionSet=new HashMap<>(); //并查集
        int[] rootMap=new int[26];
        int rootValue=1;
        for(int i=0;i<equations.length;i++)
        {
            String s=equations[i];
            if(s.charAt(1)=='=')
            {
                char ch1=s.charAt(0),ch2=s.charAt(3);
                if(rootMap[ch1-'a']==0)
                {
                    if(rootMap[ch2-'a']==0)
                    {
                        //建立一个新并查集
                        rootMap[ch1-'a']=rootValue;
                        rootMap[ch2-'a']=rootValue;
                        HashSet<Character> tempSet=new HashSet<>();
                        tempSet.add(ch1);
                        tempSet.add(ch2);
                        unionSet.put(rootValue,tempSet);
                        rootValue+=1;
                    }
                    else
                    {
                        //ch1加入ch2所在的并查集中
                        rootMap[ch1-'a']=rootMap[ch2-'a'];
                        unionSet.get(rootMap[ch2-'a']).add(ch1);
                    }
                }
                else
                {
                    if(rootMap[ch2-'a']==0)
                    {
                        //ch2加入ch1所在的并查集中
                        rootMap[ch2-'a']=rootMap[ch1-'a'];
                        unionSet.get(rootMap[ch1-'a']).add(ch2);
                    }
                    else if(ch1!=ch2 && rootMap[ch1-'a']!=rootMap[ch2-'a'])
                    {
                        //合并两个并查集
                        int index1=rootMap[ch1-'a'],index2=rootMap[ch2-'a'];
                        if(unionSet.get(index1).size()>=unionSet.get(index2).size())
                        {
                            mergeUnion(unionSet,rootMap,index1,index2);
                        }
                        else
                        {
                            mergeUnion(unionSet,rootMap,index2,index1);
                        }
                    }
                }
            }
        }

        //并查集建立完毕,接下来验证方程组的正确性
        for(int i=0;i<equations.length;i++)
        {
            String s=equations[i];
            if(s.charAt(1)=='!')
            {
                char ch1=s.charAt(0),ch2=s.charAt(3);
                if(ch1==ch2)
                {
                    return false;
                }
                else if(rootMap[ch1-'a']==rootMap[ch2-'a'] && rootMap[ch1-'a']!=0)
                {
                    return false;
                }
            }
        }
        return true;
    }

    //将一个并查集合并到另一个并查集中
    void mergeUnion(HashMap<Integer,HashSet<Character>> unionSet,int[] rootMap,int unionIndex1,int unionIndex2)
    {
        HashSet<Character> mergedSet=unionSet.get(unionIndex2); //将要被合并入其他并查集的并查集
        for(char ch:mergedSet) //更改根节点
        {
            rootMap[ch-'a']=unionIndex1;
        }
        unionSet.get(unionIndex1).addAll(unionSet.get(unionIndex2)); //合并
        unionSet.remove(unionIndex2); //删除被合并的并查集
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值