LeetCode-399. 除法求值
题目来源
题目详情
给你一个变量对数组 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 ]
示例 2:
输入: equations = [["a","b"],["b","c"],["bc","cd"]], values = [1.5,2.5,5.0], queries = [["a","c"],["c","b"],["bc","cd"],["cd","bc"]]
输出: [3.75000,0.40000,5.00000,0.20000]
示例 3:
输入: equations = [["a","b"]], values = [0.5], queries = [["a","b"],["b","a"],["a","c"],["x","y"]]
输出: [0.50000,2.00000,-1.00000,-1.00000]
提示:
1 <= equations.length <= 20
equations[i].length == 2
1 <= Ai.length, Bi.length <= 5
values.length == equations.length
0.0 < values[i] <= 20.0
1 <= queries.length <= 20
queries[i].length == 2
1 <= Cj.length, Dj.length <= 5
Ai, Bi, Cj, Dj
由小写英文字母与数字组成
题解分析
解法一:并查集
class Solution {
public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
HashMap<String, Integer> map = new HashMap<>();
MergeFindSet mergeFindSet = new MergeFindSet(equations.size() * 2);
int cnt = 0;
for(int i=0; i < equations.size(); i++){
List<String> list = equations.get(i);
String start = list.get(0);
String end = list.get(1);
if(!map.containsKey(start)){
map.put(start, cnt);
cnt++;
}
if(!map.containsKey(end)){
map.put(end, cnt);
cnt++;
}
mergeFindSet.merge(map.get(start), map.get(end), values[i]);
}
double[] res = new double[queries.size()];
for(int i=0; i<queries.size(); i++){
List<String> query = queries.get(i);
String start = query.get(0);
String end = query.get(1);
if(map.containsKey(start) && map.containsKey(end)){
res[i] = mergeFindSet.isConnect(map.get(start), map.get(end));
}else{
res[i] = -1.0;
}
}
return res;
}
class MergeFindSet{
int[] parent;
double[] weight;
MergeFindSet(int n){
parent = new int[n];
weight = new double[n];
for(int i=0; i<n; i++){
parent[i] = i;
weight[i] = 1.0;
}
}
int find(int x){
if(x == parent[x]){
return parent[x];
}else{
int tempparent = parent[x];
parent[x] = find(parent[x]);// 递归找到父节点
weight[x] = weight[x] * weight[tempparent]; // 路径压缩,重新计算权重
return parent[x];
}
}
void merge(int a, int b, double value){
int pa = find(a);
int pb = find(b);
if(pa != pb){
parent[pa] = pb;
weight[pa] = weight[b] * value / weight[a];
}
}
double isConnect(int a, int b){
int pa = find(a);
int pb = find(b);
if(pa == pb){
return weight[a] / weight[b];
}else{
return -1.0;
}
}
}
}