62
62
63
63
<!-- 这里可写通用的实现逻辑 -->
64
64
65
- 并查集。
65
+ ** 方法一: 并查集**
66
66
67
- 模板 1——朴素并查集 :
67
+ 我们可以遍历每个节点 $i$ 以及对应的左右孩子 $l$, $r$,用 $vis$ 数组记录节点是否有父节点 :
68
68
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$。
84
72
85
- 模板 2——维护 size 的并查集:
73
+ 遍历结束,判断并查集中连通分量个数是否为 $1$,若是返回 ` true ` ,否则返回 ` false ` 。
86
74
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$。
132
76
133
77
<!-- tabs:start -->
134
78
@@ -138,29 +82,24 @@ d[find(a)] = distance
138
82
139
83
``` python
140
84
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 :
146
89
if p[x] != x:
147
90
p[x] = find(p[x])
148
91
return p[x]
149
92
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
164
103
return n == 1
165
104
```
166
105
@@ -174,27 +113,20 @@ class Solution {
174
113
175
114
public boolean validateBinaryTreeNodes (int n , int [] leftChild , int [] rightChild ) {
176
115
p = new int [n];
177
- boolean [] vis = new boolean [n];
178
116
for (int i = 0 ; i < n; ++ i) {
179
117
p[i] = i;
180
118
}
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;
194
129
}
195
- vis[r] = true ;
196
- p[find(i)] = find(r);
197
- -- n;
198
130
}
199
131
}
200
132
return n == 1 ;
@@ -214,76 +146,61 @@ class Solution {
214
146
``` cpp
215
147
class Solution {
216
148
public:
217
- vector<int > p;
218
-
219
149
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
+ }
236
167
}
237
168
}
238
169
return n == 1;
239
170
}
240
-
241
- int find(int x) {
242
- if (p[x] != x) p[x] = find(p[x]);
243
- return p[x];
244
- }
245
171
};
246
172
```
247
173
248
174
### **Go**
249
175
250
176
```go
251
- var p []int
252
-
253
177
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 {
256
180
p[i] = i
257
181
}
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])
268
186
}
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--
272
199
}
273
- vis[r] = true
274
- p[find (i)] = find (r)
275
- n--
276
200
}
277
201
}
278
202
return n == 1
279
203
}
280
-
281
- func find (x int ) int {
282
- if p[x] != x {
283
- p[x] = find (p[x])
284
- }
285
- return p[x]
286
- }
287
204
```
288
205
289
206
### ** ...**
0 commit comments