Leetcode 990. 等式方程的可满足性【并查集】

问题描述

给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b""a!=b"。在这里,a 和 b 是小写字母(不一定不同),表示单字母变量名。

只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true,否则返回 false

示例 1:

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

解题报告

并查集主要用于解决一些元素分组的问题。它管理一系列不相交的集合,并支持两种操作

  • 合并(Union):把两个不相交的集合合并为一个集合
  • 查询(Find):查询两个元素是否在同一集合中。 2 ^{2}

算法步骤:

  • 将所有具有相等关系的字母进行 merge
  • 然后遍历所有不相等的关系,如果发现不相等的两个字母在同一个集合中,那么直接返回 false

同时使用了 路径压缩按秩合并 的优化策略。

实现代码

class Solution{
    public:
        unordered_map<int, int>parent, cnt; 
        int find(int index){
            return parent[index]==index?index:parent[index]=find(parent[index]);
        }
        void merge(int a, int b){
            a=find(a);
            b=find(b);
            if(a==b) return;
            // 按秩合并,为了使得合并后的子树高度尽量低,
            // 需要把高度晓得那棵子树接在高度高的那个树下
            if(cnt[a]<cnt[b]){
                parent[a]=b;
                cnt[b]+=cnt[a];
            }
            else{
                parent[b]=a;
                cnt[a]+=cnt[b];
            }
        }
        bool equationsPossible(vector<string>&equations){
            for(int i=0;i<26;i++){
                parent[i]=i;
                cnt[i]=1;
            }
            
            for (const string& str: equations) {
                if (str[1] == '=') {
                    int index1 = str[0] - 'a';
                    int index2 = str[3] - 'a';
                    merge(index1, index2);
                }
            }
            for (const string& str: equations) {
                if (str[1] == '!') {
                    int index1 = str[0] - 'a';
                    int index2 = str[3] - 'a';
                    if (find(index1) == find(index2)) {
                        return false;
                    }
                }
            }
        return true;
        }
};

参考资料

[1] Leetcode 990. 等式方程的可满足性
[2] 算法学习笔记(1) : 并查集
[3]

猜你喜欢

转载自blog.csdn.net/qq_27690765/article/details/106616078