0399. 除法求值【中等】
1. 📝 题目描述
给你一个变量对数组 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:
txt
输入:
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 ]
注意:x 是未定义的 => -1.01
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
示例 2:
txt
输入:
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]1
2
3
4
5
6
7
2
3
4
5
6
7
示例 3:
txt
输入:
equations = [["a","b"]],
values = [0.5],
queries = [["a","b"],["b","a"],["a","c"],["x","y"]]
输出:
[0.50000,2.00000,-1.00000,-1.00000]1
2
3
4
5
6
7
2
3
4
5
6
7
提示:
1 <= equations.length <= 20equations[i].length == 21 <= Ai.length, Bi.length <= 5values.length == equations.length0.0 < values[i] <= 20.01 <= queries.length <= 20queries[i].length == 21 <= Cj.length, Dj.length <= 5Ai, Bi, Cj, Dj由小写英文字母与数字组成
2. 🎯 s.1 - 带权并查集
c
// 带权并查集
char* names[1000];
double w[1000];
int par[1000];
int cnt;
int getId(char* s) {
for (int i = 0; i < cnt; i++) if (strcmp(names[i], s) == 0) return i;
names[cnt] = (char*)malloc(strlen(s) + 1);
strcpy(names[cnt], s);
par[cnt] = cnt; w[cnt] = 1.0;
return cnt++;
}
int find(int x) {
if (par[x] != x) {
int root = find(par[x]);
w[x] *= w[par[x]];
par[x] = root;
}
return par[x];
}
void unite(int a, int b, double val) {
int ra = find(a), rb = find(b);
if (ra == rb) return;
par[ra] = rb;
w[ra] = val * w[b] / w[a];
}
double* calcEquation(char*** equations, int equationsSize, int* equationsColSize,
double* values, int valuesSize, char*** queries, int queriesSize,
int* queriesColSize, int* returnSize) {
cnt = 0;
for (int i = 0; i < equationsSize; i++) {
int a = getId(equations[i][0]), b = getId(equations[i][1]);
unite(a, b, values[i]);
}
double* res = (double*)malloc(sizeof(double) * queriesSize);
*returnSize = queriesSize;
for (int i = 0; i < queriesSize; i++) {
int a = -1, b = -1;
for (int j = 0; j < cnt; j++) {
if (strcmp(names[j], queries[i][0]) == 0) a = j;
if (strcmp(names[j], queries[i][1]) == 0) b = j;
}
if (a == -1 || b == -1 || find(a) != find(b)) res[i] = -1.0;
else res[i] = w[a] / w[b];
}
for (int i = 0; i < cnt; i++) free(names[i]);
return res;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
js
/**
* @param {string[][]} equations
* @param {number[]} values
* @param {string[][]} queries
* @return {number[]}
*/
var calcEquation = function (equations, values, queries) {
const parent = new Map()
const weight = new Map() // weight[x] = x / root(x)
const find = (x) => {
if (!parent.has(x)) {
parent.set(x, x)
weight.set(x, 1.0)
}
if (parent.get(x) !== x) {
const root = find(parent.get(x))
weight.set(x, weight.get(x) * weight.get(parent.get(x)))
parent.set(x, root)
}
return parent.get(x)
}
const union = (a, b, val) => {
const ra = find(a),
rb = find(b)
if (ra === rb) return
parent.set(ra, rb)
weight.set(ra, (val * weight.get(b)) / weight.get(a))
}
for (let i = 0; i < equations.length; i++) {
union(equations[i][0], equations[i][1], values[i])
}
return queries.map(([a, b]) => {
if (!parent.has(a) || !parent.has(b)) return -1.0
if (find(a) !== find(b)) return -1.0
return weight.get(a) / weight.get(b)
})
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
py
class Solution:
def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
parent = {}
weight = {} # weight[x] = x / root(x)
def find(x):
if x not in parent:
parent[x] = x
weight[x] = 1.0
if parent[x] != x:
root = find(parent[x])
weight[x] *= weight[parent[x]]
parent[x] = root
return parent[x]
def union(a, b, val):
ra, rb = find(a), find(b)
if ra == rb:
return
parent[ra] = rb
weight[ra] = val * weight[b] / weight[a]
for (a, b), val in zip(equations, values):
union(a, b, val)
res = []
for a, b in queries:
if a not in parent or b not in parent or find(a) != find(b):
res.append(-1.0)
else:
res.append(weight[a] / weight[b])
return res1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
- 时间复杂度:
,其中 是等式数, 是查询数 - 空间复杂度:
算法思路:
- 建立带权并查集,
a / b = val即合并 a、b,权值传递除法关系- 查询时若同根则