Skip to content

Commit 3b59b1a

Browse files
committed
feat: add solutions to lc/lcof2 problem: Evaluate Division
1 parent 003ab93 commit 3b59b1a

File tree

11 files changed

+1133
-4
lines changed

11 files changed

+1133
-4
lines changed

lcof2/剑指 Offer II 111. 计算除法/README.md

+267-1
Original file line numberDiff line numberDiff line change
@@ -64,22 +64,288 @@
6464

6565
<!-- 这里可写通用的实现逻辑 -->
6666

67+
并查集。
68+
69+
模板 1——朴素并查集:
70+
71+
```python
72+
# 初始化,p存储每个点的父节点
73+
p = list(range(n))
74+
75+
# 返回x的祖宗节点
76+
def find(x):
77+
if p[x] != x:
78+
# 路径压缩
79+
p[x] = find(p[x])
80+
return p[x]
81+
82+
# 合并a和b所在的两个集合
83+
p[find(a)] = find(b)
84+
```
85+
86+
模板 2——维护 size 的并查集:
87+
88+
```python
89+
# 初始化,p存储每个点的父节点,size只有当节点是祖宗节点时才有意义,表示祖宗节点所在集合中,点的数量
90+
p = list(range(n))
91+
size = [1] * n
92+
93+
# 返回x的祖宗节点
94+
def find(x):
95+
if p[x] != x:
96+
# 路径压缩
97+
p[x] = find(p[x])
98+
return p[x]
99+
100+
# 合并a和b所在的两个集合
101+
if find(a) != find(b):
102+
size[find(b)] += size[find(a)]
103+
p[find(a)] = find(b)
104+
```
105+
106+
模板 3——维护到祖宗节点距离的并查集:
107+
108+
```python
109+
# 初始化,p存储每个点的父节点,d[x]存储x到p[x]的距离
110+
p = list(range(n))
111+
d = [0] * n
112+
113+
# 返回x的祖宗节点
114+
def find(x):
115+
if p[x] != x:
116+
t = find(p[x])
117+
d[x] += d[p[x]]
118+
p[x] = t
119+
return p[x]
120+
121+
# 合并a和b所在的两个集合
122+
p[find(a)] = find(b)
123+
d[find(a)] = distance
124+
```
125+
126+
对于本题,具备等式关系的所有变量构成同一个集合,同时,需要维护一个权重数组 w,初始时 `w[i] = 1`。对于等式关系如 `a / b = 2`,令 `w[a] = 2`。在 `find()` 查找祖宗节点的时候,同时进行路径压缩,并更新节点权重。
127+
67128
<!-- tabs:start -->
68129

69130
### **Python3**
70131

71132
<!-- 这里可写当前语言的特殊实现逻辑 -->
72133

73134
```python
74-
135+
class Solution:
136+
def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
137+
n = len(equations)
138+
p = list(range(n << 1))
139+
w = [1.0] * (n << 1)
140+
141+
def find(x):
142+
if p[x] != x:
143+
origin = p[x]
144+
p[x] = find(p[x])
145+
w[x] *= w[origin]
146+
return p[x]
147+
148+
mp = {}
149+
idx = 0
150+
for i, e in enumerate(equations):
151+
a, b = e[0], e[1]
152+
if a not in mp:
153+
mp[a] = idx
154+
idx += 1
155+
if b not in mp:
156+
mp[b] = idx
157+
idx += 1
158+
pa, pb = find(mp[a]), find(mp[b])
159+
if pa == pb:
160+
continue
161+
p[pa] = pb
162+
w[pa] = w[mp[b]] * values[i] / w[mp[a]]
163+
164+
res = []
165+
for q in queries:
166+
c, d = q[0], q[1]
167+
if c not in mp or d not in mp:
168+
res.append(-1.0)
169+
else:
170+
pa, pb = find(mp[c]), find(mp[d])
171+
res.append(w[mp[c]] / w[mp[d]] if pa == pb else -1.0)
172+
return res
75173
```
76174

77175
### **Java**
78176

79177
<!-- 这里可写当前语言的特殊实现逻辑 -->
80178

81179
```java
180+
class Solution {
181+
private int[] p;
182+
private double[] w;
183+
184+
public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
185+
int n = equations.size();
186+
p = new int[n << 1];
187+
w = new double[n << 1];
188+
for (int i = 0; i < p.length; ++i) {
189+
p[i] = i;
190+
w[i] = 1.0;
191+
}
192+
Map<String, Integer> mp = new HashMap<>(n << 1);
193+
int idx = 0;
194+
for (int i = 0; i < n; ++i) {
195+
List<String> e = equations.get(i);
196+
String a = e.get(0), b = e.get(1);
197+
if (!mp.containsKey(a)) {
198+
mp.put(a, idx++);
199+
}
200+
if (!mp.containsKey(b)) {
201+
mp.put(b, idx++);
202+
}
203+
int pa = find(mp.get(a)), pb = find(mp.get(b));
204+
if (pa == pb) {
205+
continue;
206+
}
207+
p[pa] = pb;
208+
w[pa] = w[mp.get(b)] * values[i] / w[mp.get(a)];
209+
}
210+
int m = queries.size();
211+
double[] res = new double[m];
212+
for (int i = 0; i < m; ++i) {
213+
String c = queries.get(i).get(0), d = queries.get(i).get(1);
214+
Integer id1 = mp.get(c), id2 = mp.get(d);
215+
if (id1 == null || id2 == null) {
216+
res[i] = -1.0;
217+
} else {
218+
int pa = find(id1), pb = find(id2);
219+
res[i] = pa == pb ? w[id1] / w[id2] : -1.0;
220+
}
221+
}
222+
return res;
223+
}
224+
225+
private int find(int x) {
226+
if (p[x] != x) {
227+
int origin = p[x];
228+
p[x] = find(p[x]);
229+
w[x] *= w[origin];
230+
}
231+
return p[x];
232+
}
233+
}
234+
```
235+
236+
### **C++**
237+
238+
```cpp
239+
class Solution {
240+
public:
241+
vector<int> p;
242+
vector<double> w;
243+
244+
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
245+
int n = equations.size();
246+
for (int i = 0; i < (n << 1); ++i)
247+
{
248+
p.push_back(i);
249+
w.push_back(1.0);
250+
}
251+
unordered_map<string, int> mp;
252+
int idx = 0;
253+
for (int i = 0; i < n; ++i)
254+
{
255+
auto e = equations[i];
256+
string a = e[0], b = e[1];
257+
if (mp.find(a) == mp.end()) mp[a] = idx++;
258+
if (mp.find(b) == mp.end()) mp[b] = idx++;
259+
int pa = find(mp[a]), pb = find(mp[b]);
260+
if (pa == pb) continue;
261+
p[pa] = pb;
262+
w[pa] = w[mp[b]] * values[i] / w[mp[a]];
263+
}
264+
int m = queries.size();
265+
vector<double> res;
266+
for (int i = 0; i < m; ++i)
267+
{
268+
string c = queries[i][0], d = queries[i][1];
269+
if (mp.find(c) == mp.end() || mp.find(d) == mp.end()) res.push_back(-1.0);
270+
else
271+
{
272+
int pa = find(mp[c]), pb = find(mp[d]);
273+
res.push_back(pa == pb ? w[mp[c]] / w[mp[d]] : -1.0);
274+
}
275+
}
276+
return res;
277+
}
278+
279+
int find(int x) {
280+
if (p[x] != x)
281+
{
282+
int origin = p[x];
283+
p[x] = find(p[x]);
284+
w[x] *= w[origin];
285+
}
286+
return p[x];
287+
}
288+
};
289+
```
82290

291+
### **Go**
292+
293+
```go
294+
var p []int
295+
var w []float64
296+
297+
func calcEquation(equations [][]string, values []float64, queries [][]string) []float64 {
298+
n := len(equations)
299+
p = make([]int, (n<<1)+10)
300+
w = make([]float64, (n<<1)+10)
301+
for i := 0; i < (n<<1)+10; i++ {
302+
p[i] = i
303+
w[i] = 1.0
304+
}
305+
mp := make(map[string]int)
306+
idx := 1
307+
for i, e := range equations {
308+
a, b := e[0], e[1]
309+
if mp[a] == 0 {
310+
mp[a] = idx
311+
idx++
312+
}
313+
if mp[b] == 0 {
314+
mp[b] = idx
315+
idx++
316+
}
317+
pa, pb := find(mp[a]), find(mp[b])
318+
if pa == pb {
319+
continue
320+
}
321+
p[pa] = pb
322+
w[pa] = w[mp[b]] * values[i] / w[mp[a]]
323+
}
324+
var res []float64
325+
for _, q := range queries {
326+
c, d := q[0], q[1]
327+
if mp[c] == 0 || mp[d] == 0 {
328+
res = append(res, -1.0)
329+
} else {
330+
pa, pb := find(mp[c]), find(mp[d])
331+
if pa == pb {
332+
res = append(res, w[mp[c]]/w[mp[d]])
333+
} else {
334+
res = append(res, -1.0)
335+
}
336+
}
337+
}
338+
return res
339+
}
340+
341+
func find(x int) int {
342+
if p[x] != x {
343+
origin := p[x]
344+
p[x] = find(p[x])
345+
w[x] *= w[origin]
346+
}
347+
return p[x]
348+
}
83349
```
84350

85351
### **...**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
class Solution {
2+
public:
3+
vector<int> p;
4+
vector<double> w;
5+
6+
vector<double> calcEquation(vector<vector<string>>& equations, vector<double>& values, vector<vector<string>>& queries) {
7+
int n = equations.size();
8+
for (int i = 0; i < (n << 1); ++i)
9+
{
10+
p.push_back(i);
11+
w.push_back(1.0);
12+
}
13+
unordered_map<string, int> mp;
14+
int idx = 0;
15+
for (int i = 0; i < n; ++i)
16+
{
17+
auto e = equations[i];
18+
string a = e[0], b = e[1];
19+
if (mp.find(a) == mp.end()) mp[a] = idx++;
20+
if (mp.find(b) == mp.end()) mp[b] = idx++;
21+
int pa = find(mp[a]), pb = find(mp[b]);
22+
if (pa == pb) continue;
23+
p[pa] = pb;
24+
w[pa] = w[mp[b]] * values[i] / w[mp[a]];
25+
}
26+
int m = queries.size();
27+
vector<double> res;
28+
for (int i = 0; i < m; ++i)
29+
{
30+
string c = queries[i][0], d = queries[i][1];
31+
if (mp.find(c) == mp.end() || mp.find(d) == mp.end()) res.push_back(-1.0);
32+
else
33+
{
34+
int pa = find(mp[c]), pb = find(mp[d]);
35+
res.push_back(pa == pb ? w[mp[c]] / w[mp[d]] : -1.0);
36+
}
37+
}
38+
return res;
39+
}
40+
41+
int find(int x) {
42+
if (p[x] != x)
43+
{
44+
int origin = p[x];
45+
p[x] = find(p[x]);
46+
w[x] *= w[origin];
47+
}
48+
return p[x];
49+
}
50+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
var p []int
2+
var w []float64
3+
4+
func calcEquation(equations [][]string, values []float64, queries [][]string) []float64 {
5+
n := len(equations)
6+
p = make([]int, (n<<1)+10)
7+
w = make([]float64, (n<<1)+10)
8+
for i := 0; i < (n<<1)+10; i++ {
9+
p[i] = i
10+
w[i] = 1.0
11+
}
12+
mp := make(map[string]int)
13+
idx := 1
14+
for i, e := range equations {
15+
a, b := e[0], e[1]
16+
if mp[a] == 0 {
17+
mp[a] = idx
18+
idx++
19+
}
20+
if mp[b] == 0 {
21+
mp[b] = idx
22+
idx++
23+
}
24+
pa, pb := find(mp[a]), find(mp[b])
25+
if pa == pb {
26+
continue
27+
}
28+
p[pa] = pb
29+
w[pa] = w[mp[b]] * values[i] / w[mp[a]]
30+
}
31+
var res []float64
32+
for _, q := range queries {
33+
c, d := q[0], q[1]
34+
if mp[c] == 0 || mp[d] == 0 {
35+
res = append(res, -1.0)
36+
} else {
37+
pa, pb := find(mp[c]), find(mp[d])
38+
if pa == pb {
39+
res = append(res, w[mp[c]]/w[mp[d]])
40+
} else {
41+
res = append(res, -1.0)
42+
}
43+
}
44+
}
45+
return res
46+
}
47+
48+
func find(x int) int {
49+
if p[x] != x {
50+
origin := p[x]
51+
p[x] = find(p[x])
52+
w[x] *= w[origin]
53+
}
54+
return p[x]
55+
}

0 commit comments

Comments
 (0)