leetcode399. Evaluate Division

Time:2020-1-7

Subject requirements

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.

Given the relationship between some letters, can we calculate the multiple relationship between other letters?
As knowna/b=2.0 b/c=3.0Ask if you can calculatea/c, b/a, a/e, a/a, x/xThe value. If it cannot be calculated, – 1 is returned. Herex/xThe value of because it is not known in the condition whether x is equal to zero, its true result cannot be calculated, and it also needs to return – 1.

Ideas and codes

If we regard the divisor and the dividend as the vertex of the graph, we try to do the weight of the edge between the divisor and the dividend. Namelya/b=2.0The weight of the edge representing point a pointing to point B is 2.0, while the total center of the edge of point B pointing to point a is 1 / 2.0 = 0.5.

Therefore, we can convert the input expression into a weighted digraph, and the problem of the topic is transformed into whether we can find an edge between two points. If we can’t find an edge, we will return – 1, otherwise we will return the product of the weight of each edge on the path.

The code is as follows:

public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        //Chain representation of Graphs
        Map<String, List<String>> pairs = new HashMap<>();
        //Weight of each edge on a graph
        Map<String, List<Double>> valuedPairs = new HashMap<>();
        for(int i = 0 ; i < equations.size() ; i++) {
            //Get the i-th equation
            List<String> equation = equations.get(i);
            String multiplied = equation.get (0); // dividend
            String multiplier = equation.get (1); // divisor
            //If the dividend has never been added to the graph, it is initialized as a vertex in the graph
            if(!pairs.containsKey(multiplied)) {
                pairs.put(multiplied, new ArrayList<>());
                valuedPairs.put(multiplied, new ArrayList<>());
            }
            //If a divisor has never been added to the graph, it is initialized as a vertex in the graph
            if(!pairs.containsKey(multiplier)) {
                pairs.put(multiplier, new ArrayList<>());
                valuedPairs.put(multiplier, new ArrayList<>());
            }
            //Add weights for edges and edges
            pairs.get(multiplied).add(multiplier);
            pairs.get(multiplier).add(multiplied);
            valuedPairs.get(multiplied).add(values[i]);
            valuedPairs.get(multiplier).add(1.0 / values[i]);
        }
        
        // result set
        double[] result = new double[queries.size()];
        for(int i = 0 ; i<queries.size() ; i++) {
            //In a graph, the divisor is used as the vertex, and the depth first traverses the graph until the vertex whose value is the divisor is found
            result[i] = dfs(queries.get(i).get(0), queries.get(i).get(1), pairs, valuedPairs, new HashSet<>(), 1.0);
            result[i] = result[i]==0.0 ? -1.0 : result[i];
        }
        return result;
    }
    
    public double dfs(String multiplied, String multiplier, Map<String, List<String>> pairs, Map<String, List<Double>> valuedPairs, Set<String> visited, double curResult) {
        //If the graph does not contain the dividend vertex, the value of the expression cannot be obtained
        if(!pairs.containsKey(multiplied)) return 0.0;
        //If the divisor is visited again, a loop is found, the depth first traversal result fails and is discarded directly
        if(visited.contains(multiplied)) return 0.0;
        //Returns 1.0 if the dividend equals the divisor
        if(multiplied.equals(multiplier)) return curResult;
        visited.add(multiplied);
        //Get all adjacent vertices of the current divisor
        List<String> multipliers = pairs.get(multiplied);
        //Get the weight of all adjacent edges
        List<Double> multiplierValues = valuedPairs.get(multiplied);
        double tmp = 0.0;
        for(int i = 0 ; i<multipliers.size() ; i++) {
            //Take the adjacent point as the new vertex, continue depth first traversal
            //At this time, the value of curresult in the calling method represents the value of the original adjacent point divided by the adjacent point
            //If a / b = 2, B / C = 3, then a = 2B, so when we use B as the adjacency point to find C, we need to record that the original dividend is twice the present dividend
            tmp = dfs(multipliers.get(i), multiplier, pairs, valuedPairs, visited, curResult * multiplierValues.get(i));
            //Find non-zero path, end depth first traversal
            if(tmp != 0.0){
                break;
            }
        }
        visited.remove(multiplied);
        return tmp;
    }

Recommended Today

Array of algorithms — sum of three numbers

Sum of three numbers difficultysecondary Here is an array of N integersnums, judgmentnumsAre there three elements a, B, C in a such that a + B + C = 0? Please find all triples that satisfy the condition and do not repeat.be careful:The answer cannot contain duplicate triples. Example:Given array nums = [- 1, 0, […]