Problem
Equations are given in the format A / B = k, where A and B are variables represented as strings, and k is a real number (floating point number). Given some queries, return the answers. If the answer does not exist, return -1.0.
Example:
Given a / b = 2.0, b / c = 3.0.
queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
return [6.0, 0.5, -1.0, 1.0, -1.0 ].
The input is: vector
According to the example above:
equations = [ ["a", "b"], ["b", "c"] ],
values = [2.0, 3.0],
queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].
The input is always valid. You may assume that evaluating the queries will result in no division by zero and there is no contradiction.
Solution - Updated Union Find
class Solution {
public double[] calcEquation(String[][] equations, double[] values, String[][] queries) {
Map graph = new HashMap<>();
Map ratio = new HashMap<>();
double[] res = new double[queries.length];
for (int i = 0; i < equations.length; i++) {
String p0 = find(equations[i][0], graph, ratio);
String p1 = find(equations[i][1], graph, ratio);
graph.put(p0, p1);
ratio.put(p0, values[i] * ratio.get(equations[i][1]) / ratio.get(equations[i][0]));
}
for (int i = 0; i < queries.length; i++) {
if (!graph.containsKey(queries[i][0]) || !graph.containsKey(queries[i][1])) {
res[i] = -1.0;
continue;
}
String p0 = find(queries[i][0], graph, ratio);
String p1 = find(queries[i][1], graph, ratio);
if (!p0.equals(p1)) {
res[i] = -1.0;
continue;
}
res[i] = ratio.get(queries[i][0]) / ratio.get(queries[i][1]);
}
return res;
}
private String find(String str, Map graph, Map ratio) {
if (!graph.containsKey(str)) {
graph.put(str, str);
ratio.put(str, 1.0);
return str;
}
if (graph.get(str).equals(str)) return str;
String parent = graph.get(str);
String ancestor = find(parent, graph, ratio);
graph.put(str, ancestor);
ratio.put(str, ratio.get(str)*ratio.get(parent));
return ancestor;
}
}
Solution - DFS
class Solution {
public double[] calcEquation(String[][] equations, double[] values, String[][] queries) {
double[] res = new double[queries.length];
Set dict = new HashSet<>();
for (String[] pair: equations) {
dict.add(pair[0]);
dict.add(pair[1]);
}
for (int i = 0; i < queries.length; i++) {
String[] pair = queries[i];
if (!dict.contains(pair[0]) || !dict.contains(pair[1])) {
res[i] = -1.0d;
} else {
res[i] = dfs(equations, values, pair, new HashSet());
}
}
return res;
}
private double dfs(String[][] equations, double[] values, String[] pair, Set set) {
for (int i = 0; i < equations.length; i++) {
if (pair[0].equals(equations[i][0]) && pair[1].equals(equations[i][1])) return values[i];
if (pair[0].equals(equations[i][1]) && pair[1].equals(equations[i][0])) return 1.0d/values[i];
}
for (int i = 0; i < equations.length; i++) {
if (!set.contains(i) && pair[0].equals(equations[i][0])) {
set.add(i);
double temp = dfs(equations, values, new String[]{equations[i][1], pair[1]}, set)*values[i];
if (temp > 0) return temp;
else set.remove(i);
}
if (!set.contains(i) && pair[0].equals(equations[i][1])) {
set.add(i);
double temp = dfs(equations, values, new String[]{equations[i][0], pair[1]}, set)/values[i];
if (temp > 0) return temp;
else set.remove(i);
}
}
return -1.0d;
}
}
Solution - Union Find
class Solution {
public double[] calcEquation(String[][] equations, double[] values, String[][] queries) {
Map graph = new HashMap<>();
Map ratio = new HashMap<>();
for (int i = 0; i < equations.length; i++) {
union(graph, ratio, equations[i][0], equations[i][1], values[i]);
}
double[] res = new double[queries.length];
for (int i = 0; i < queries.length; i++) {
String s1 = queries[i][0], s2 = queries[i][1];
if (!graph.containsKey(s1) || !graph.containsKey(s2) || !find(graph, ratio, s1).equals(find(graph, ratio, s2))) {
res[i] = -1.0d;
} else {
res[i] = ratio.get(s1)/ratio.get(s2);
}
}
return res;
}
private void union(Map graph, Map ratio, String s1, String s2, double value) {
if (!graph.containsKey(s1)) {
graph.put(s1, s1);
ratio.put(s1, 1.0d);
}
if (!graph.containsKey(s2)) {
graph.put(s2, s2);
ratio.put(s2, 1.0d);
}
String p1 = find(graph, ratio, s1);
String p2 = find(graph, ratio, s2);
graph.put(p1, p2);
ratio.put(p1, value*ratio.get(s2)/ratio.get(s1));
}
private String find(Map graph, Map ratio, String str) {
if (str.equals(graph.get(str))) return str;
String parent = graph.get(str);
String ancestor = find(graph, ratio, parent);
graph.put(str, ancestor);
ratio.put(str, ratio.get(str)*ratio.get(parent));
return ancestor;
}
}