
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-除法求值