LeetCode-Evaluate Division

LiBlog發表於2016-09-12

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<pair<string, string>> euqations, vector<double>& values, vector<pair<string, string>> query . where equations.size() == values.size(),the values are positive. this represents the equations.return vector<double>. .
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.

Analysis:

We need to build a graph to describe the input equations: for equations[i], equations[i][0] -> equations[i][1] = values[i] while equations[i][1] -> equations[i][0] = 1/values[i].

After getting the graph, we can search the graph for each query. During every search, we record each calculated result in the graph for later use.

NOTE: to be compatiable with possible values[i] == 0, we can use Double type instead of double type. For x/y==0, we do not record y/x, i.e., set y/x as null.

Solution:

public class Solution {
    public double[] calcEquation(String[][] equations, double[] values, String[][] query) {
        HashMap<String,Integer> indexMap = new HashMap<String,Integer>();
        int nums = 0;
        for (String[] equation : equations){
            if (!indexMap.containsKey(equation[0])){
                indexMap.put(equation[0],nums++);
            }
            if (!indexMap.containsKey(equation[1])){
                indexMap.put(equation[1],nums++);
            }
        }
        Double[][] graph = new Double[nums][nums];
        for (int i=0;i<equations.length;i++){
            int num1 = indexMap.get(equations[i][0]), num2 = indexMap.get(equations[i][1]);
            if (values[i]!=0){
                graph[num2][num1] = 1/values[i];
            }
            graph[num1][num2] = values[i];
            graph[num1][num1] = 1.0;
            graph[num2][num2] = 1.0;
        }
        
        double[] res = new double[query.length];
        for (int i=0;i<query.length;i++){
            if (!indexMap.containsKey(query[i][0]) || !indexMap.containsKey(query[i][1])){
                res[i] = -1;
            } else {
                int num1 = indexMap.get(query[i][0]), num2 = indexMap.get(query[i][1]);
                res[i] = calcQuery(graph,num1,num2);
            }
        }
        return res;
    }
    
    public double calcQuery(Double[][] graph, int start, int end){
        if (graph[start][end]!= null){
            return graph[start][end];
        }
        
        Queue<Integer> queue = new LinkedList<Integer>();
        for (int i=0;i<graph.length;i++)
            if (graph[start][i]!=null){
                queue.add(i);
            }
            
        while (!queue.isEmpty()){
            int cur = queue.poll();
            for (int i=0;i<graph.length;i++)
                if (graph[cur][i]!=null && graph[start][i]==null){
                    graph[start][i] = graph[start][cur]*graph[cur][i];
                    graph[i][start] = 1/graph[start][i];
                    queue.add(i);
                    if (i==end){
                        return graph[start][end];
                    }
                }
        }
        return -1.0;
    }
}