LeetCode: Evaluate Division
This question is asked at Bloomberg, Uber, Amazon, and Microsoft.
You are given an Array of variable pairs equations and an array of real numbers values, where equations[i] = [Ai, Bi] and values[i] represent the equation Ai/Bi = values[i]. Each Ai or Bi is a string that represents a single variable.
You are also given some queries where queries[j] = [Cj, Dj] represents the jth query where you must find the Cj/Dj. Return the answer to all of the queries. If there isn't any answer that menas that we need to return 1.0.
So let's have an example here.
Input: equations = [["a","b"],["b","c"]], values = [2.0,3.0], queries = [["a","c"],["b","a"],["a","e"],["a","a"],["x","x"]]
Output: [6.00000,0.50000,-1.00000,1.00000,-1.00000]
Explanation:
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 ]
Now, let's see how one would approach this problem and the corresponding solution. So, let's go over the graph solution here.
Let's say a/b = 2 and b/c = 3. so this means that
b/a = 1/2 and c/b = 1/3. This means that a/c = a/b * b/c which is equivalent to 2 * 3 = 6 and c/a = 1/6.
As a result, we can reformulate the equations with a graph data structure, where each variable can be represented as a node in the graph and the division relationship between the variables can be modelled as an edge between the node and its corresponding weight.
So we can just transform this problem into a path searching problem and return the cumulative products as a result. This can be either done through BFS or DFS.class Solution {
public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
//build the graph from the equation.
for(int i = 0; i < equations.size(); i++) {
List<String> equation = equations.get(i);
String dividend = equation.get(0), divisor = equation.get(1);
double quotient = values(i);
//add the dividend and the divisor
if(!graph.containsKey(dividend) {graph.put(dividend, new HashMap<String, Double>()};
if(!graph.containsKey(divisor) {graph.put(dividend, new HashMap<String, Double>()};
//put dividend/divisor in the graph.
graph.get(dividend).put(divisor, quotient);
graph.get(divisor).put(dividend, 1/quotient);
}
//evaluate each query through backtracking and verifying there exists a path from dividend to divisor
double[] results = new double[queries.size()];
for(int i = 0; i < queries.size(); i++) {
List<String> query = queries.get(i);
String dividend = query.get(0), divisor = query.get(1);
if(!graph.containsKey(dividend) || !graph.containsKey(divisor)) results[i] = -1.0;
else if (dividend == divisor) results[i] = 1.0;
else {
HashSet<String> visited = new HashSet<>();
results[i] = backtrackEvaluate(graph, dividend, divisor, 1, visited);
}
}
return results;
}
private double backtrackEvaluate(HashMap<String, HashMap<String, Double>> graph, String currNode, String targetNode, double accProduct, Set<String> visited) {
//mark visit
visited.add(currNode);
double ret = -1.0;
Map<String, Double> neighbors = graph.get(currNode);
if(neighbors.containsKey(targetNode)) ret = accProduct * neighbors.get(targetNode);
else {
for(Map.Entry<String, Double> pair: neighbors.entrySet()) {
String nextNode = pair.getKey();
if(visited.contains(nextNode)) continue;
ret = backtrackEvaluate(graph, nextNode, targetNode, accProduct * pair.getValue(), visited);
if(ret != -1.0) break;
}
}
//unmark node
visited.remove(currNode);
return ret;
}
}


Comments
Post a Comment