- 除法求值
给你一个变量对数组 equations 和一个实数值数组 values 作为已知条件,其中 equations[i] = [Ai, Bi] 和 values[i] 共同表示等式 Ai / Bi = values[i] 。每个 Ai 或 Bi 是一个表示单个变量的字符串。
另有一些以数组 queries 表示的问题,其中 queries[j] = [Cj, Dj] 表示第 j 个问题,请你根据已知条件找出 Cj / Dj = ? 的结果作为答案。
返回 所有问题的答案 。如果存在某个无法确定的答案,则用 -1.0 替代这个答案。如果问题中出现了给定的已知条件中没有出现的字符串,也需要用 -1.0 替代这个答案。
注意:输入总是有效的。你可以假设除法运算中不会出现除数为 0 的情况,且不存在任何矛盾的结果。
示例 1:
输入:equations = [[“a”,“b”],[“b”,“c”]], values = [2.0,3.0], queries = [[“a”,“c”],[“b”,“a”],[“a”,“e”],[“a”,“a”],[“x”,“x”]]
输出:[6.00000,0.50000,-1.00000,1.00000,-1.00000]
解释:
条件:a / b = 2.0, b / c = 3.0
问题:a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?
结果:[6.0, 0.5, -1.0, 1.0, -1.0 ]
1.原理介绍
此为union的原理
class Solution {
private Map<String, String> parents = new HashMap<>();
//类似于parents[]数组
private Map<String, Double> values = new HashMap<>();
//因为要记录权值,新设一个map,表示父节点/当前的节点
public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
//先建立点的关系,union
int len = equations.size();
for(int i = 0; i < len; i++){
String x = equations.get(i).get(0);
String y = equations.get(i).get(1);
union(x, y, values[i]);
}
len = queries.size();
double[] ans = new double[len];
for(int i = 0; i < len; i++){
String x = queries.get(i).get(0);
String y = queries.get(i).get(1);
if(!(parents.containsKey(x) && parents.containsKey(y))){
//只要有一个不存在,
ans[i] = -1;
continue;
}
if(x.equals(y)){
ans[i] = 1;
continue;
}
//如果不相同,找到各自根节点,先判断二者是否连通
String r1 = findParent(x);
String r2 = findParent(y);
if(!r1.equals(r2)){
ans[i] = -1;
continue;
}
//最后一种情况,确是二者处于连通状态
ans[i] = pm(y) / pm(x);//x/y恰好为二者的pm的相反数
}
return ans;
}
public void union(String x, String y, double val){
//已经包含了加入元素的操作
add(x);
add(y);
//找到各自的根节点
String r1 = findParent(x);
String r2 = findParent(y);
if(!r1.equals(r2)){
//parents.put(r1, r2);//注意这里不能写反了,前面的为子节点
parents.put(r2, r1);
//关键对应的权值数组/map也要进行更新
values.put(r2, val * (pm(x) / pm(y)));
//此时更新的就是两个找到的根节点的权值之比,恰为x/y * pm(x)/pm(y)
}
}
public double pm(String x){
//表示x节点的权值到根节点权值的乘积
double val = 1;
while(!x.equals(parents.get(x))){
val *= values.get(x);
x = parents.get(x);
}
return val;
}
public String findParent(String x){
while(!x.equals(parents.get(x))){
//其实形式是差不多的
x = parents.get(x);
}
return x;
}
public void add(String now){
if(!parents.containsKey(now)){
parents.put(now, now);
values.put(now, 1.0);
}
}
}