等式方程的可满足性
判断给定的字符方程数组(形式如 "a==b" 或 "a!=b")是否存在一组合理的变量赋值。如果能够找到一种赋值方式使得数组中所有的相等和不等条件同时成立,则返回 true,否则返回 false。
LeetCode1分钟阅读

这道题可以通过 并查集(Union-Find) 数据结构高效解决。
- 关系抽象:
a == b表示变量a和b属于同一个集合(具有连通性)。a != b表示变量a和b不能属于同一个集合。
- 两阶段处理:
- 第一步(合并):先遍历所有
==的方程,将相等的变量合并到同一个集合中。 - 第二步(校验):再遍历所有
!=的方程,检查不等号两侧的变量是否在同一个集合中。如果已经在同一个集合中,说明存在矛盾,直接返回false;若全部检查完毕均无冲突,则返回true。
- 第一步(合并):先遍历所有
class Solution {private: int parent[26];
int find(int x) { if (parent[x] != x) { parent[x] = find(parent[x]); // 路径压缩 } return parent[x]; }
void unionSet(int x, int y) { int rootX = find(x); int rootY = find(y); if (rootX != rootY) { parent[rootX] = rootY; } }
public: bool equationsPossible(vector<string>& equations) { // 1. 初始化并查集,每个字母的根节点初始为自己 for (int i = 0; i < 26; ++i) { parent[i] = i; }
// 2. 第一遍遍历:处理所有 '==' 方程,合并连通分量 for (const string& eq : equations) { if (eq[1] == '=') { int var1 = eq[0] - 'a'; int var2 = eq[3] - 'a'; unionSet(var1, var2); } }
// 3. 第二遍遍历:处理所有 '!=' 方程,校验是否存在矛盾 for (const string& eq : equations) { if (eq[1] == '!') { int var1 = eq[0] - 'a'; int var2 = eq[3] - 'a'; if (find(var1) == find(var2)) { return false; // 不等号两侧变量在同一集合,矛盾 } } }
return true; }};- 时间复杂度:,其中 是方程数组
equations的长度, 是字母表大小。包含路径压缩的并查集操作近乎 ,因此整体时间复杂度接近 。 - 空间复杂度:,只需要固定大小为 26 的数组用于保存父节点信息。