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<pair<string, string>> equations, vector<double>& values, vector<pair<string, string>> queries , where equations.size() == values.size(), and the values are positive. This represents the equations. Return vector<double>.

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<String, String> graph = new HashMap<>();
        Map<String, Double> 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<String, String> graph, Map<String, Double> 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<String> 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<Integer>());
            }
        }
        return res;
    }
    private double dfs(String[][] equations, double[] values, String[] pair, Set<Integer> 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<String, String> graph = new HashMap<>();
        Map<String, Double> 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<String, String> graph, Map<String, Double> 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<String, String> graph, Map<String, Double> 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;
    }
}

linspiration
161 声望53 粉丝