每日一题 2020/6/8 990. 等式方程的可满足性(c++) 并查集

给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 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 以满足满足这两个方程。

示例 3:

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

示例 4:

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

示例 5:

输入:["c==c","b==d","x!=z"]
输出:true

我自己做的时候只想到了用集合,但是无法处理当两个变量都不属于任何一个集合的时候,怎么选择插入哪个集合。

这题考察并查集知识,很遗憾在看答案前我没有想起数据结构课程上学的内容。看了后很快就想起来了,说明上课还是有用的嘛,不一定一直记得,但是再看一遍相关内容就能很快唤醒大脑的记忆细胞。并查集主要有查找find()和构造unite()两个函数,具体实现通过一个数组记录父节点信息,同一个集合所有节点的根节点相同,当一个节点的父节点是它本身时,说明该节点是根节点。构造并查集时则将第一个变量的根节点的父节点指向第二个变量的根节点,这样两个变量都指向同一个根节点,即属于同一个并查集。

遍历两遍字符串数组,第一遍遍历的时候根据'=='来建立并查集,第二遍的时候根据’!=‘进行判断,如果两个变量的根节点相同,则返回false。

class Solution {
    vector<int> parent;
public:    
    Solution(){
        for(int i=0;i<26;i++){
            parent.push_back(i);
        }
    }
    bool equationsPossible(vector<string>& equations) {
        int len=equations.size();
        for(int i=0;i<len;i++){
            if(equations[i][1]=='='){
                int num1=equations[i][0]-'a';
                int num2=equations[i][3]-'a';
                unite(num1,num2);
            }
        }
        for(int i=0;i<len;i++){
            if(equations[i][1]=='!'){
                int num1=equations[i][0]-'a';
                int num2=equations[i][3]-'a';
                if(find(num1)==find(num2))
                    return false;
            }
        }
        return true;
    }
    int find(int idx){
        if(parent[idx]==idx)
            return idx;
        parent[idx]=find(parent[idx]);
        return parent[idx];
    }
    void unite(int idx1,int idx2){
        parent[find(idx1)]=find(idx2);
    }
};

注意开始的时候我是直接 vector<int>parent(26,0)来初始化parent数组的,但是报错,查了一下说是在类内只能用等号初始化即复制构造函数和初始化列表进行初始化。可以改成vector<int>parent{0,1,2...24,25}。但是好傻,不如直接像上面代码那样。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值