Skip to content

Commit 39f43f5

Browse files
committed
feat: update solutions to lc problem: No.1361
No.1361.Validate Binary Tree Nodes
1 parent 0b3aa9d commit 39f43f5

File tree

6 files changed

+178
-319
lines changed

6 files changed

+178
-319
lines changed

solution/1300-1399/1361.Validate Binary Tree Nodes/README.md

+66-149
Original file line numberDiff line numberDiff line change
@@ -62,73 +62,17 @@
6262

6363
<!-- 这里可写通用的实现逻辑 -->
6464

65-
并查集
65+
**方法一:并查集**
6666

67-
模板 1——朴素并查集
67+
我们可以遍历每个节点 $i$ 以及对应的左右孩子 $l$, $r$,用 $vis$ 数组记录节点是否有父节点
6868

69-
```python
70-
# 初始化,p存储每个点的父节点
71-
p = list(range(n))
72-
73-
# 返回x的祖宗节点
74-
def find(x):
75-
if p[x] != x:
76-
# 路径压缩
77-
p[x] = find(p[x])
78-
return p[x]
79-
80-
81-
# 合并a和b所在的两个集合
82-
p[find(a)] = find(b)
83-
```
69+
- 若孩子节点已存在父节点,说明有多个父亲,不满足条件,直接返回 `false`
70+
- 若孩子节点与父节点已经处于同一个连通分量,说明会形成环,不满足条件,直接返回 `false`
71+
- 否则,进行合并,并且将 $vis$ 数组对应位置置为 `true`,同时将连通分量个数减去 $1$。
8472

85-
模板 2——维护 size 的并查集:
73+
遍历结束,判断并查集中连通分量个数是否为 $1$,若是返回 `true`,否则返回 `false`
8674

87-
```python
88-
# 初始化,p存储每个点的父节点,size只有当节点是祖宗节点时才有意义,表示祖宗节点所在集合中,点的数量
89-
p = list(range(n))
90-
size = [1] * n
91-
92-
# 返回x的祖宗节点
93-
def find(x):
94-
if p[x] != x:
95-
# 路径压缩
96-
p[x] = find(p[x])
97-
return p[x]
98-
99-
# 合并a和b所在的两个集合
100-
if find(a) != find(b):
101-
size[find(b)] += size[find(a)]
102-
p[find(a)] = find(b)
103-
```
104-
105-
模板 3——维护到祖宗节点距离的并查集:
106-
107-
```python
108-
# 初始化,p存储每个点的父节点,d[x]存储x到p[x]的距离
109-
p = list(range(n))
110-
d = [0] * n
111-
112-
# 返回x的祖宗节点
113-
def find(x):
114-
if p[x] != x:
115-
t = find(p[x])
116-
d[x] += d[p[x]]
117-
p[x] = t
118-
return p[x]
119-
120-
# 合并a和b所在的两个集合
121-
p[find(a)] = find(b)
122-
d[find(a)] = distance
123-
```
124-
125-
对于本题,遍历每个节点 i 以及对应的左右孩子 l, r,用 vis 数组记录节点是否有父节点:
126-
127-
- 若孩子节点已存在父节点,说明有多个父亲,不满足条件,直接返回 false。
128-
- 若孩子节点与父节点已经处于同一个连通分量,说明会形成环,不满足条件,直接返回 false。
129-
- 否则,进行合并,并将节点 i 分别与 l, r 进行合并。
130-
131-
遍历结束,判断连通分量个数是否为 1,若是返回 true,否则返回 false。
75+
时间复杂度 $O(n \times \alpha(n))$,空间复杂度 $O(n)$。其中 $n$ 为节点个数,而 $\alpha(n)$ 为阿克曼函数的反函数,即反阿克曼函数,其值小于 $5$。
13276

13377
<!-- tabs:start -->
13478

@@ -138,29 +82,24 @@ d[find(a)] = distance
13882

13983
```python
14084
class Solution:
141-
def validateBinaryTreeNodes(self, n: int, leftChild: List[int], rightChild: List[int]) -> bool:
142-
p = list(range(n))
143-
vis = [False] * n
144-
145-
def find(x):
85+
def validateBinaryTreeNodes(
86+
self, n: int, leftChild: List[int], rightChild: List[int]
87+
) -> bool:
88+
def find(x: int) -> int:
14689
if p[x] != x:
14790
p[x] = find(p[x])
14891
return p[x]
14992

150-
for i in range(n):
151-
l, r = leftChild[i], rightChild[i]
152-
if l != -1:
153-
if vis[l] or find(i) == find(l):
154-
return False
155-
p[find(i)] = find(l)
156-
vis[l] = True
157-
n -= 1
158-
if r != -1:
159-
if vis[r] or find(i) == find(r):
160-
return False
161-
p[find(i)] = find(r)
162-
vis[r] = True
163-
n -= 1
93+
p = list(range(n))
94+
vis = [False] * n
95+
for i, (a, b) in enumerate(zip(leftChild, rightChild)):
96+
for j in (a, b):
97+
if j != -1:
98+
if vis[j] or find(i) == find(j):
99+
return False
100+
p[find(i)] = find(j)
101+
vis[j] = True
102+
n -= 1
164103
return n == 1
165104
```
166105

@@ -174,27 +113,20 @@ class Solution {
174113

175114
public boolean validateBinaryTreeNodes(int n, int[] leftChild, int[] rightChild) {
176115
p = new int[n];
177-
boolean[] vis = new boolean[n];
178116
for (int i = 0; i < n; ++i) {
179117
p[i] = i;
180118
}
181-
for (int i = 0, t = n; i < t; ++i) {
182-
int l = leftChild[i], r = rightChild[i];
183-
if (l != -1) {
184-
if (vis[l] || find(i) == find(l)) {
185-
return false;
186-
}
187-
vis[l] = true;
188-
p[find(i)] = find(l);
189-
--n;
190-
}
191-
if (r != -1) {
192-
if (vis[r] || find(i) == find(r)) {
193-
return false;
119+
boolean[] vis = new boolean[n];
120+
for (int i = 0, m = n; i < m; ++i) {
121+
for (int j : new int[] {leftChild[i], rightChild[i]}) {
122+
if (j != -1) {
123+
if (vis[j] || find(i) == find(j)) {
124+
return false;
125+
}
126+
p[find(i)] = find(j);
127+
vis[j] = true;
128+
--n;
194129
}
195-
vis[r] = true;
196-
p[find(i)] = find(r);
197-
--n;
198130
}
199131
}
200132
return n == 1;
@@ -214,76 +146,61 @@ class Solution {
214146
```cpp
215147
class Solution {
216148
public:
217-
vector<int> p;
218-
219149
bool validateBinaryTreeNodes(int n, vector<int>& leftChild, vector<int>& rightChild) {
220-
p.resize(n);
221-
for (int i = 0; i < n; ++i) p[i] = i;
222-
vector<bool> vis(n, false);
223-
for (int i = 0, t = n; i < t; ++i) {
224-
int l = leftChild[i], r = rightChild[i];
225-
if (l != -1) {
226-
if (vis[l] || find(i) == find(l)) return false;
227-
vis[l] = true;
228-
p[find(i)] = find(l);
229-
--n;
230-
}
231-
if (r != -1) {
232-
if (vis[r] || find(i) == find(r)) return false;
233-
vis[r] = true;
234-
p[find(i)] = find(r);
235-
--n;
150+
int p[n];
151+
iota(p, p + n, 0);
152+
bool vis[n];
153+
memset(vis, 0, sizeof(vis));
154+
function<int(int)> find = [&](int x) {
155+
return p[x] == x ? x : p[x] = find(p[x]);
156+
};
157+
for (int i = 0, m = n; i < m; ++i) {
158+
for (int j : {leftChild[i], rightChild[i]}) {
159+
if (j != -1) {
160+
if (vis[j] || find(i) == find(j)) {
161+
return false;
162+
}
163+
p[find(i)] = find(j);
164+
vis[j] = true;
165+
--n;
166+
}
236167
}
237168
}
238169
return n == 1;
239170
}
240-
241-
int find(int x) {
242-
if (p[x] != x) p[x] = find(p[x]);
243-
return p[x];
244-
}
245171
};
246172
```
247173
248174
### **Go**
249175
250176
```go
251-
var p []int
252-
253177
func validateBinaryTreeNodes(n int, leftChild []int, rightChild []int) bool {
254-
p = make([]int, n)
255-
for i := 0; i < n; i++ {
178+
p := make([]int, n)
179+
for i := range p {
256180
p[i] = i
257181
}
258-
vis := make([]bool, n)
259-
for i, t := 0, n; i < t; i++ {
260-
l, r := leftChild[i], rightChild[i]
261-
if l != -1 {
262-
if vis[l] || find(i) == find(l) {
263-
return false
264-
}
265-
vis[l] = true
266-
p[find(i)] = find(l)
267-
n--
182+
var find func(int) int
183+
find = func(x int) int {
184+
if p[x] != x {
185+
p[x] = find(p[x])
268186
}
269-
if r != -1 {
270-
if vis[r] || find(i) == find(r) {
271-
return false
187+
return p[x]
188+
}
189+
vis := make([]bool, n)
190+
for i, a := range leftChild {
191+
for _, j := range []int{a, rightChild[i]} {
192+
if j != -1 {
193+
if vis[j] || find(i) == find(j) {
194+
return false
195+
}
196+
p[find(i)] = find(j)
197+
vis[j] = true
198+
n--
272199
}
273-
vis[r] = true
274-
p[find(i)] = find(r)
275-
n--
276200
}
277201
}
278202
return n == 1
279203
}
280-
281-
func find(x int) int {
282-
if p[x] != x {
283-
p[x] = find(p[x])
284-
}
285-
return p[x]
286-
}
287204
```
288205

289206
### **...**

0 commit comments

Comments
 (0)