
class Solution {    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {        int equationsSize = equations.size();        UnionFind unionFind = new UnionFind(2 * equationsSize); //最大需要两倍空间(每个list有两个字母)        //第一步,预处理,将变量的值与id进行映射,使得并查集的底层用数组实现,方便编码        Map<String, Integer> map = new HashMap<>(2 * equationsSize);//初始化map将字母关系转化为数字        int id = 0; //对应values中索引和映射字母        for (int i = 0; i < equationsSize; i++) {            List<String> equation = equations.get(i);            String var1 = equation.get(0);            String var2 = equation.get(1);            if (!map.containsKey(var1)) {                map.put(var1, id++);            }            if (!map.containsKey(var2)) {                map.put(var2, id++);            }            //并查询查询之前执行一次合并操作            unionFind.union(map.get(var1), map.get(var2), values[i]);        }        //第二步  做查询        int queriesSize = queries.size();        double[] res = new double[queriesSize];        for (int i = 0; i < queriesSize; i++) {            String var1 = queries.get(i).get(0);            String var2 = queries.get(i).get(1);            //得到需要查询的字母对应的id            Integer id1 = map.get(var1);            Integer id2 = map.get(var2);            if (id1 == null || id2 == null) {                res[i] = -1.0;            } else {                //两个节点都存在,则转化为和父节点的关系进行比较                res[i] = unionFind.isConnected(id1, id2);            }        }        return res;    }    class UnionFind {        private int[] parent; //表示每个节点对应的父节点的id        private double[] weight; //表示节点指向父节点的权值        public UnionFind(int n) {            this.parent = new int[n];            this.weight = new double[n];            //初始化,所有的父节点开始都是指向自己            for (int i = 0; i < n; i++) {                parent[i] = i;                weight[i] = 1.0d;            }        }        /**         * 合并操作         *         * @param x,y   两个节点         * @param value 有向边的权值         */        public void union(int x, int y, double value) {            //找到两个节点对应的父节点            int rootx = find(x);            int rooty = find(y);            if (rootx == rooty) {                return;            }            parent[rootx] = rooty;            weight[rootx] = weight[y] * value / weight[x];        }        /**         * 路径压缩         *         * @param id 输入节点的id         * @return 根节点的id         */        private int find(int id) {            if (id != parent[id]) {                //根据上一次节点的权值来更新当前节点的权值                int preNode = parent[id];                parent[id] = find(parent[id]);                weight[id] *= weight[preNode];            }            return parent[id];        }        public double isConnected(int x, int y) {            int rootX = find(x);            int rootY = find(y);            if (rootX == rootY) {                return weight[x] / weight[y];            } else {                //说明不在一个集合中                return -1;            }        }    }}
hot100-除法求值