Calculation of 399 division of force deduction problem

Posted by sanlove on Thu, 30 Dec 2021 22:37:59 +0100

Give you a variable pair array equations and a real value array values as known conditions, where equations[i] = [Ai, Bi] and values[i] jointly represent the equation Ai / Bi = values[i]. Each Ai or Bi is a string representing a single variable.

There are also some problems represented by array queries, where queries[j] = [Cj, Dj] represents the j-th problem. Please find Cj / Dj =? As the answer.

Return answers to all questions. If there is an uncertain answer, replace it with - 1.0. If there is a string in the question that does not appear in the given known conditions, you also need to replace the answer with - 1.0.

Note: input is always valid. You can assume that there will be no divisor of 0 in the division operation, and there are no conflicting results.

Example 1:

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:
Conditions: a / b = 2.0, b / c = 3.0
Question: A / C =?, b / a = ?, a / e = ?, a / a = ?, x / x = ?
Result: [6.0, 0.5, - 1.0, 1.0, - 1.0]
Example 2:

Input: equations = [["a", "B"], ["B", "C"], ["BC", "CD"]], values = [1.5,2.5,5.0], queries = ["a", "C"], ["C", "B"], ["BC", "CD"], ["CD", "BC"]]
Output: [3.75000,0.40000,5.00000,0.20000]
Example 3:

Input: equations = [["a","b"]], values = [0.5], queries = [["a","b"],["b","a"],["a","c"],["x","y"]]
Output: [0.50000,2.00000, - 1.00000, - 1.00000]

1. The first step is to use a hash table to store each existing string, treat each string as a point, and use the hash table to map this point into an integer (subscript index). The second step is to store the points and weights that can be directly connected to each point as an edge through conditions. The last step is to perform breadth first traversal to get the value that can be obtained from each point to other points.

Graph + directed weight edge + DFS. From this question, we can summarize how to build a map, build edges, and assign weights.

class Solution {
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        int nvars = 0;//Number of statistical points
        Map<String,Integer> variables = new HashMap<>();//Use a hash table to store each node and map each node to an integer

        int n = equations.size();
        for (int i = 0;i < n;i++) {//Add all the strings that appear in equations to the hash table
            if (!variables.containsKey(equations.get(i).get(0))) {
                variables.put(equations.get(i).get(0),nvars);
                nvars++;
            }
            if (!variables.containsKey(equations.get(i).get(1))) {
                variables.put(equations.get(i).get(1),nvars);
                nvars++;
            }
        }

        //For each point, all points directly connected to it and the corresponding weights are stored
        List<Pair>[] edges = new List[nvars];
        for (int i = 0;i < nvars;i++) {
            edges[i] = new ArrayList<Pair>();
        }
        for (int i = 0;i < n;i++) {//Connect each set of conditions
            int va = variables.get(equations.get(i).get(0));
            int vb = variables.get(equations.get(i).get(1));
            edges[va].add(new Pair(vb,values[i]));
            edges[vb].add(new Pair(va,1/values[i]));
        }

        int queriesCount = queries.size();
        double[] ret = new double[queriesCount];
        for (int i = 0;i < queriesCount;i++) {
            List<String> query = queries.get(i);
            double result = -1.0;
            //Only when both strings are conditions existing in the hash table, you need to continue the calculation, otherwise it is - 1.0
            if (variables.containsKey(query.get(0)) && variables.containsKey(query.get(1))) {
                int ia = variables.get(query.get(0));//Get the subscript of the first point
                int ib = variables.get(query.get(1));//Get the subscript of the second point
                if (ia == ib) {
                    result = 1.0;
                } else {
                    Queue<Integer> points = new LinkedList<>();//Use a queue to store the traversed nodes (breadth first traversal)
                    points.offer(ia);
                    double[] ratios = new double[nvars];//Stores the ratio of traversal from the starting point to each remaining point
                    Arrays.fill(ratios,-1.0);
                    ratios[ia] = 1.0;//The start ratio is initialized to 1.0

                    while (!points.isEmpty() && ratios[ib] < 0) { //Ratios less than 0 indicates that the current ib point has not been accessed
                        int x = points.poll();//Take out the current starting point
                        for (Pair pair : edges[x]) {//Traverse every edge that this starting point can reach
                            int y = pair.index;
                            double val = pair.value;
                            if (ratios[y] < 0) {
                                ratios[y] = ratios[x] * val;//Calculate the rate of reaching this point
                                points.offer(y);//Add new points to the queue
                            }
                        }
                    }
                    result = ratios[ib];
                }
            }
            ret[i] = result;
        }

        return ret;
    }
}

class Pair{
    int index;//Subscript representing the point to which the current node is connected
    double value;//Represents the weight

    Pair(int index,double value) {
        this.index = index;
        this.value = value;
    }
}

2.Floyd algorithm. In the case of a large number of queries, if you search independently for each query, the efficiency will become lower. Therefore, we might as well preprocess the graph first, and then answer each query in a short time. In this problem, we can use Floyd algorithm to calculate the distance between any two points in advance.

reference resources: Shortest path template + parsing - (floyd algorithm) _ytuyzh's blog - CSDN blog _floydalgorithm

class Solution {
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        int nvars = 0;//Number of points
        Map<String,Integer> variables = new HashMap<>();//The hash table stores each point and maps to the subscript of each point

        int n = equations.size();
        for (int i = 0;i < n;i++) {//Store each existing string in the hash table
            if (!variables.containsKey(equations.get(i).get(0))) {
                variables.put(equations.get(i).get(0),nvars);
                nvars++;
            }
            if (!variables.containsKey(equations.get(i).get(1))) {
                variables.put(equations.get(i).get(1),nvars);
                nvars++;
            }
        }
        //Floyd algorithm
        double[][] graph = new double[nvars][nvars];
        for (int i = 0;i < nvars;i++) {
            Arrays.fill(graph[i],-1.0);
        } 
        for (int i = 0;i < n;i++) {//Initialize the dynamic array and assign values to the points that can be directly connected
            int va = variables.get(equations.get(i).get(0));
            int vb = variables.get(equations.get(i).get(1));
            graph[va][vb] = values[i];
            graph[vb][va] = 1.0 / values[i];
        }
        for (int k = 0;k < nvars;k++) {//It means intermediary point
            for (int i = 0;i < nvars;i++) {
                for (int j = 0;j < nvars;j++) {
                    if (graph[i][k] > 0 && graph[k][j] > 0) {//Only when the product is greater than 0, that is, from point i to point j can be updated
                        graph[i][j] = graph[i][k] * graph[k][j];
                    }
                }
            }
        }

        int queriesCount = queries.size();
        double[] ret = new double[queriesCount];
        for (int i = 0;i < queriesCount;i++) {
            List<String> query = queries.get(i);
            double result = -1.0;
            if (variables.containsKey(query.get(0)) && variables.containsKey(query.get(1))) {//The result can only be found if both strings exist
                int ia = variables.get(query.get(0));
                int ib = variables.get(query.get(1));
                if (graph[ia][ib] > 0) {
                    result = graph[ia][ib];
                }
            }
            ret[i] = result;
        }

        return ret;
    }
}

Question source: Force buckle

Topics: Algorithm leetcode