专栏:力扣刷题录_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]
是 '='
对并查集陌生的读者,可以移步另一篇博客学习或者回顾一下
我们可以看到题目中的一句话,“只有当可以将整数分配给变量名,以便满足所有给定的方程时才返回 true
,否则返回 false
”。这些相同的变量也就可以合并为同一个集合,而不相等的不属于通过一个集合。
我们可以注意到其中变量名只有小写字母,所以我们可以只开26大小的父指针数组,通过将字符-'a'映射到对应位置
上面的2.2和2.3要注意下标的映射
和解法1差不多,就是把并查集的找根函数用lambda表达式实现了。
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;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;
}