Welcome to Subscribe On Youtube

Formatted question description: https://leetcode.ca/all/990.html

990. Satisfiability of Equality Equations (Medium)

Given an array equations of strings that represent relationships between variables, each string equations[i] has length 4 and takes one of two different forms: "a==b" or "a!=b".  Here, a and b are lowercase letters (not necessarily different) that represent one-letter variable names.

Return true if and only if it is possible to assign integers to variable names so as to satisfy all the given equations.

 

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. 1 <= equations.length <= 500
  2. equations[i].length == 4
  3. equations[i][0] and equations[i][3] are lowercase letters
  4. equations[i][1] is either '=' or '!'
  5. equations[i][2] is '='

Related Topics:
Union Find, Graph

Solution 1. Union Find

// OJ: https://leetcode.com/problems/satisfiability-of-equality-equations/
// Time: O(N)
// Space: O(1)
class UnionFind {
    unordered_map<char, char> id;
    unordered_map<char, int> rank;
public:
    void connect(char a, char b) {
        int x = find(a), y = find(b);
        if (x == y) return;
        if (rank[x] <= rank[y]) {
            id[x] = y;
            if (rank[x] == rank[y]) rank[y]++;
        } else id[y] = x;
    }
    char find(char a) {
        if (!id.count(a)) {
            rank[a] = 1;
            id[a] = a;
        }
        return id[a] == a ? a : (id[a] = find(id[a]));
    }
};
class Solution {
public:
    bool equationsPossible(vector<string>& equations) {
        UnionFind uf;
        for (auto e : equations) {
            if (e[1] == '=') uf.connect(e[0], e[3]);
        }
        for (auto e : equations) {
            if (e[1] == '!' && uf.find(e[0]) == uf.find(e[3])) return false;
        }
        return true;
    }
};

Solution 2. Union Find

// OJ: https://leetcode.com/problems/satisfiability-of-equality-equations/
// Time: O(N)
// Space: O(1)
class Solution {
    int uf[26];
    int find(int x) {
        return uf[x] == x ? x : (uf[x] = find(uf[x]));
    }
public:
    bool equationsPossible(vector<string>& equations) {
        for (int i = 0; i < 26; ++i) uf[i] = i;
        for (auto e : equations) {
            if (e[1] == '=') uf[find(e[0] - 'a')] = find(e[3] - 'a'); 
        }
        for (auto e : equations) {
            if (e[1] == '!' && find(e[0] - 'a') == find(e[3] - 'a')) return false;
        }
        return true;
    }
};

Solution 3. Graph Coloring (DFS)

// OJ: https://leetcode.com/problems/satisfiability-of-equality-equations/
// Time: O(N)
// Space: O(N)
class Solution {
    vector<bool> visited = vector<bool>(26, false);
    int color[26];
    vector<vector<int>> adj = vector<vector<int>>(26);
    void dfs(int u, int c) {
        visited[u] = true;
        color[u] = c;
        for (auto v : adj[u]) {
            if (!visited[v]) dfs(v, c);
        }
    }
public:
    bool equationsPossible(vector<string>& equations) {
        for (auto e : equations) {
            if (e[1] != '=') continue;
            adj[e[0] - 'a'].push_back(e[3] - 'a');
            adj[e[3] - 'a'].push_back(e[0] - 'a');
        }
        for (int i = 0, c = 0; i < 26; ++i) {
            if (!visited[i]) dfs(i, c++);
        }
        for (auto e : equations) {
            if (e[1] == '!' && color[e[0] - 'a'] == color[e[3] - 'a']) return false;
        }
        return true;
    }
};
  • class Solution {
        public boolean equationsPossible(String[] equations) {
            Map<Character, Set<Character>> equalMap = new HashMap<Character, Set<Character>>();
            Map<Character, Set<Character>> unequalMap = new HashMap<Character, Set<Character>>();
            for (String equation : equations) {
                char var1 = equation.charAt(0), var2 = equation.charAt(3);
                if (equation.charAt(1) == '=') {
                    Set<Character> equalSet1 = equalMap.getOrDefault(var1, new HashSet<Character>());
                    equalSet1.add(var1);
                    Set<Character> equalSet2 = equalMap.getOrDefault(var2, new HashSet<Character>());
                    equalSet2.add(var2);
                    equalSet1.addAll(equalSet2);
                    equalSet2.addAll(equalSet1);
                    for (char var : equalSet1)
                        equalMap.put(var, equalSet1);
                    for (char var : equalSet2)
                        equalMap.put(var, equalSet2);
                } else if (var1 == var2)
                    return false;
            }
            for (String equation : equations) {
                if (equation.charAt(1) == '!') {
                    char var1 = equation.charAt(0), var2 = equation.charAt(3);
                    Set<Character> equalSet = equalMap.getOrDefault(var1, new HashSet<Character>());
                    if (equalSet.contains(var2))
                        return false;
                }
            }
            return true;
        }
    }
    
    ############
    
    class Solution {
        private int[] p;
    
        public boolean equationsPossible(String[] equations) {
            p = new int[26];
            for (int i = 0; i < 26; ++i) {
                p[i] = i;
            }
            for (String e : equations) {
                int a = e.charAt(0) - 'a', b = e.charAt(3) - 'a';
                if (e.charAt(1) == '=') {
                    p[find(a)] = find(b);
                }
            }
            for (String e : equations) {
                int a = e.charAt(0) - 'a', b = e.charAt(3) - 'a';
                if (e.charAt(1) == '!' && find(a) == find(b)) {
                    return false;
                }
            }
            return true;
        }
    
        private int find(int x) {
            if (p[x] != x) {
                p[x] = find(p[x]);
            }
            return p[x];
        }
    }
    
  • // OJ: https://leetcode.com/problems/satisfiability-of-equality-equations/
    // Time: O(N)
    // Space: O(1)
    class UnionFind {
        unordered_map<char, char> id;
        unordered_map<char, int> rank;
    public:
        void connect(char a, char b) {
            int x = find(a), y = find(b);
            if (x == y) return;
            if (rank[x] <= rank[y]) {
                id[x] = y;
                if (rank[x] == rank[y]) rank[y]++;
            } else id[y] = x;
        }
        char find(char a) {
            if (!id.count(a)) {
                rank[a] = 1;
                id[a] = a;
            }
            return id[a] == a ? a : (id[a] = find(id[a]));
        }
    };
    class Solution {
    public:
        bool equationsPossible(vector<string>& equations) {
            UnionFind uf;
            for (auto e : equations) {
                if (e[1] == '=') uf.connect(e[0], e[3]);
            }
            for (auto e : equations) {
                if (e[1] == '!' && uf.find(e[0]) == uf.find(e[3])) return false;
            }
            return true;
        }
    };
    
  • class Solution:
        def equationsPossible(self, equations: List[str]) -> bool:
            def find(x):
                if p[x] != x:
                    p[x] = find(p[x])
                return p[x]
    
            p = list(range(26))
            for e in equations:
                a, b = ord(e[0]) - ord('a'), ord(e[-1]) - ord('a')
                if e[1] == '=':
                    p[find(a)] = find(b)
            for e in equations:
                a, b = ord(e[0]) - ord('a'), ord(e[-1]) - ord('a')
                if e[1] == '!' and find(a) == find(b):
                    return False
            return True
    
    ############
    
    class Solution(object):
        def equationsPossible(self, equations):
            """
            :type equations: List[str]
            :rtype: bool
            """
            self.m = collections.defaultdict(list)
            for eq in equations:
                if eq[1] == '=':
                    self.m[eq[0]].append(eq[3])
                    self.m[eq[3]].append(eq[0])
            for eq in equations:
                if eq[1] == '!':
                    if self.find(set(), eq[0], eq[3]) or self.find(set(), eq[3], eq[0]):
                        return False
            return True
            
        def find(self, visited, begin, end):
            if begin in visited:
                return False
            visited.add(begin)
            if begin == end:
                return True
            for n in self.m[begin]:
                if self.find(visited, n, end):
                    return True
            return False
    
  • func equationsPossible(equations []string) bool {
    	p := make([]int, 26)
    	for i := 1; i < 26; i++ {
    		p[i] = i
    	}
    	var find func(x int) int
    	find = func(x int) int {
    		if p[x] != x {
    			p[x] = find(p[x])
    		}
    		return p[x]
    	}
    	for _, e := range equations {
    		a, b := int(e[0]-'a'), int(e[3]-'a')
    		if e[1] == '=' {
    			p[find(a)] = find(b)
    		}
    	}
    	for _, e := range equations {
    		a, b := int(e[0]-'a'), int(e[3]-'a')
    		if e[1] == '!' && find(a) == find(b) {
    			return false
    		}
    	}
    	return true
    }
    
  • class UnionFind {
        private parent: number[];
    
        constructor() {
            this.parent = Array.from({ length: 26 }).map((_, i) => i);
        }
    
        find(index: number) {
            if (this.parent[index] === index) {
                return index;
            }
            this.parent[index] = this.find(this.parent[index]);
            return this.parent[index];
        }
    
        union(index1: number, index2: number) {
            this.parent[this.find(index1)] = this.find(index2);
        }
    }
    
    function equationsPossible(equations: string[]): boolean {
        const uf = new UnionFind();
        for (const [a, s, _, b] of equations) {
            if (s === '=') {
                const index1 = a.charCodeAt(0) - 'a'.charCodeAt(0);
                const index2 = b.charCodeAt(0) - 'a'.charCodeAt(0);
                uf.union(index1, index2);
            }
        }
        for (const [a, s, _, b] of equations) {
            if (s === '!') {
                const index1 = a.charCodeAt(0) - 'a'.charCodeAt(0);
                const index2 = b.charCodeAt(0) - 'a'.charCodeAt(0);
                if (uf.find(index1) === uf.find(index2)) {
                    return false;
                }
            }
        }
        return true;
    }
    
    

All Problems

All Solutions