[leetCode]399. 除法求值

题目

https://leetcode-cn.com/problems/evaluate-division/

[leetCode]399. 除法求值_第1张图片

并查集

class Solution {
     
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
     
        int equationsSize = equations.size();

        // 当equations中变量全步相同时顶点数量为 2 倍的 equationsSize
        UnionFind unionFind = new UnionFind(2 * equationsSize);
        // 并查集底层操作数字更加方便,将变量的值与id做映射,防止hash表自动扩容需要传入变量值
        Map<String, Integer> hashMap = new HashMap<>(2 * equationsSize);
        int id = 0;
        for (int i = 0; i < equationsSize; i++) {
     
            List<String> equation = equations.get(i);
            String var1 = equation.get(0);
            String var2 = equation.get(1);
            if (!hashMap.containsKey(var1)) {
     
                hashMap.put(var1, id);
                id++;
            }
            if (!hashMap.containsKey(var2)) {
     
                hashMap.put(var2, id);
                id++;
            }
            // 在并查集中进行合并操作,将变量1与变量2对应的id进行合并, 并且传入对应的权值
            unionFind.union(hashMap.get(var1), hashMap.get(var2), values[i]);
        }
        // 查询
        int queriesSize = queries.size();
        double[] res = new double[queriesSize];
        for (int i = 0; i < queriesSize; i++) {
     
            // 拿到queries中两个变量
            String var1 = queries.get(i).get(0);
            String var2 = queries.get(i).get(1);
            // 两个变量对应于并查集中的id
            Integer id1 = hashMap.get(var1);
            Integer id2 = hashMap.get(var2);
            // 如果id为null则说明这两个变量没有出现在equations中
            if (id1 == null || id2 == null) {
     
                res[i] = -1.0;
            } else {
     
                // 两个变量的比值对应于它们父节点权值的比值
                res[i] = unionFind.isConnected(id1, id2);
            }
        }
        return res;
    }

    private class UnionFind {
     

        private int[] parent;
        /**
        *   结点指向父结点的权值
        */
        private double[] weight;

        public UnionFind(int n) {
     
            parent = new int[n];
            weight = new double[n];
            for (int i = 0; i < n; i++) {
     
                parent[i] = i;// 每个结点指向自己
                weight[i] = 1.0d;
            }
        }

        public void union(int x, int y, double value) {
     
            // 查找到两个变量根结点所对应的id
            int rootX = find(x);
            int rootY = find(y);
            // 两个变量的根结点相等说明不需要合并
            if (rootX == rootY) {
     
                return;
            }
            parent[rootX] = rootY;
            //        rX--wX-rY
            //   wX  /       /  wY
            //      x-value-y
            weight[rootX] = weight[y] * value / weight[x];
        }

        // 返回根结点所对应的id, 路径压缩,将经过的结点全部连接在根结点上
        public int find(int x) {
     
            if (x != parent[x]) {
     
                // 保存上一个结点id的值
                int origin = parent[x];
                parent[x] = find(parent[x]);
                weight[x] *= weight[origin]; 
            }
            return parent[x];
        }

        public double isConnected(int x, int y) {
     
            int rootX = find(x);
            int rootY = find(y);
            if (rootX == rootY) {
     
                return weight[x] / weight[y];
            }
            return -1.0d;
        }
    }
}

你可能感兴趣的:(LeetCode,#,并查集)