并查集-990.等式方程的可满足性-力扣(LeetCode)
个人主页:1白天的黑夜1-CSDN博客
专栏:力扣刷题录_1白天的黑夜1的博客-CSDN博客、企鹅程序员:Linux 系统与网络编程_1白天的黑夜1的博客-CSDN博客
一、题目解析
1、1 <= equations.length <= 500
2、equations[i].length == 4
3、equations[i][0]
和 equations[i][3]
是小写字母
4、equations[i][1]
要么是 '='
,要么是 '!'
5、equations[i][2]
是 '='
二、算法原理
对并查集陌生的读者,可以移步另一篇博客学习或者回顾一下
高阶数据结构-并查集-CSDN博客
我们可以看到题目中的一句话,“只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true
,否则返回 false
”。这些相同的变量也就可以合并为同一个集合,而不相等的不属于通过一个集合。
解法1:自己造轮子(并查集)
我们可以注意到其中变量名只有小写字母,所以我们可以只开26大小的父指针数组,通过将字符-'a'映射到对应位置
具体步骤:
1、粘贴写好的并查集,并通过UnionFindSet()构造函数创建一个大小为26的数组
2、通过分析样例存在==和!=,先处理==
2.1、因为长度固定为4,所以可通过迭代器访问下标为1的字符,如果是'=',则可以合并等式两边下标为0和下标为3的字符
2.2、再次遍历,如果是'!',则判断等式两边字符是否在同一集合,如果在同一集合,则违背要求,所以可以直接返回false
3、如果第二次遍历后,没有违背属于同一集合的要求,则可以返回true
上面的2.2和2.3要注意下标的映射
解法2:lambda表达式
和解法1差不多,就是把并查集的找根函数用lambda表达式实现了。
具体步骤:
1、创建一个大小为26的vector并全部初始化为-1
2、先对下标为1,字符是'='的表达式处理,将表达式两边的字符合并为同一集合
3、再次遍历,对下标为1,字符是'!'的表达式处理,判断表达式两边的字符是否属于同一集合,如果属于同一集合,则违背!=要求,所以返回false
4、最后直接返回true
结合算法原理或者自己的想法,先去敲一敲,试一试,提升自己的代码能力
990. 等式方程的可满足性 - 力扣(LeetCode)
三、代码示例
解法1:
class UnionFindSet
{
public:UnionFindSet(size_t n):_ufs(n, -1){ }void Union(int x1,int x2)//并{int root1 = FindRoot(x1);int root2 = FindRoot(x2);//属于同一个集合没必要合并if(root1 == root2) return;//小的做根if (root1 > root2) swap(root1, root2);_ufs[root1] += _ufs[root2];_ufs[root2] = root1;}int FindRoot(int x)//找根{int parent = x;while (_ufs[parent] >= 0){parent = _ufs[parent];}return parent;}bool InSet(int x1,int x2){ return FindRoot(x1) == FindRoot(x2);}size_t SetSize(){size_t size = 0;for (size_t i = 0; i < _ufs.size(); i++){if (_ufs[i] < 0) ++size;}return size;}private:vector<int> _ufs;
};//解法1:造轮子bool equationsPossible(vector<string>& equations){UnionFindSet ufs(26);//相等的放在同一个集合中for(auto& str : equations){if(str[1] == '='){ufs.Union(str[0]-'a',str[3]-'a');}}//判断不等的在不在一个集合中for(auto& str : equations){if(str[1] == '!'){if(ufs.InSet(str[0]-'a',str[3]-'a'))return false;}}return true;}
解法2:
//解法2;lambda表达式bool equationsPossible(vector<string>& equations){vector<int> ufs(26,-1);auto findRoot = [&ufs](int x){while(ufs[x]>=0) x = ufs[x];return x;};//第一先把相等的值加到一个集合中for(auto& str : equations){if(str[1] == '='){int root1 = findRoot(str[0]-'a');int root2 = findRoot(str[3]-'a');if(root1 != root2){ufs[root1] += ufs[root2];ufs[root2] = root1;}}}//第二看不相等的在不在一个集合,在就矛盾了for(auto& str : equations){if(str[1] == '!'){int root1 = findRoot(str[0]-'a');int root2 = findRoot(str[3]-'a');if(root1 == root2){return false;}}}return true;}