990. Satisfiability of Equality Equations
问题:
给定多个字符串定义:某个小写字母==(!=)另一个小写字母
求这些定义中,有互相矛盾的情况吗?
有矛盾,返回false,否则返回true。
Example 1: Input: ["a==b","b!=a"] Output: false Explanation: If we assign say, a = 1 and b = 1, then the first equation is satisfied, but not the second. There is no way to assign the variables to satisfy both equations. Example 2: Input: ["b==a","a==b"] Output: true Explanation: We could assign a = 1 and b = 1 to satisfy both equations. Example 3: Input: ["a==b","b==c","a==c"] Output: true Example 4: Input: ["a==b","b!=c","c==a"] Output: false Example 5: Input: ["c==c","b==d","x!=z"] Output: true Note: 1 <= equations.length <= 500 equations[i].length == 4 equations[i][0] and equations[i][3] are lowercase letters equations[i][1] is either '=' or '!' equations[i][2] is '='
解法:并查集(Disjoint Set)
先遍历一遍所有字符串定义,将==连接的两个小写字母 连接。
再遍历一次所有字符串定义,对于!=两边的两个小写字母,检测是否已经连接,
若已经连接,则说明矛盾,返回false。
全部遍历完毕,都没有返回,则证明全部不矛盾,返回true。
代码参考:
1 class Solution { 2 public: 3 bool equationsPossible(vector<string>& equations) { 4 DisjointSet ds(26); 5 for(string& eq:equations) { 6 if(eq[1]=='=') { 7 ds.merge(eq[0]-'a', eq[3]-'a'); 8 } 9 } 10 for(string& eq:equations) { 11 if(eq[1]=='!') { 12 if(ds.isConnected(eq[0]-'a', eq[3]-'a')) return false; 13 } 14 } 15 return true; 16 } 17 };
并查集:
1 class DisjointSet { 2 public: 3 DisjointSet(int n):root(n, 0), rank(n, 0) { 4 for(int i=0; i<n; i++) root[i]=i; 5 } 6 int find(int i) { 7 if(i!=root[i]) { 8 root[i] = find(root[i]); 9 } 10 return root[i]; 11 } 12 void merge(int x, int y) { 13 int x_root = find(x); 14 int y_root = find(y); 15 if(x_root==y_root) return; 16 if(rank[x_root]>rank[y_root]) { 17 root[y_root] = x_root; 18 } else if(rank[x_root]<rank[y_root]) { 19 root[x_root] = y_root; 20 } else { 21 root[y_root] = x_root; 22 rank[x_root] ++; 23 } 24 return; 25 } 26 bool isConnected(int x, int y) { 27 int x_root = find(x); 28 int y_root = find(y); 29 return x_root == y_root; 30 } 31 private: 32 vector<int> root; 33 vector<int> rank; 34 };