@@ -92,7 +92,20 @@ class Node {
92
92
93
93
<!-- solution:start -->
94
94
95
- ### 方法一
95
+ ### 方法一:哈希表 + DFS
96
+
97
+ 我们用一个哈希表 $\textit{g}$ 记录原图中的每个节点和它的拷贝节点之间的对应关系,然后进行深度优先搜索。
98
+
99
+ 我们定义函数 $\text{dfs}(node)$,它的功能是返回 $\textit{node}$ 节点的拷贝节点。$\text{dfs}(node)$ 的过程如下:
100
+
101
+ - 如果 $\textit{node}$ 是 $\text{null}$,那么 $\text{dfs}(node)$ 的返回值是 $\text{null}$。
102
+ - 如果 $\textit{node}$ 在 $\textit{g}$ 中,那么 $\text{dfs}(node)$ 的返回值是 $\textit{g}[ node] $。
103
+ - 否则我们创建一个新的节点 $\textit{cloned}$,并将 $\textit{g}[ node] $ 的值设为 $\textit{cloned}$,然后遍历 $\textit{node}$ 的所有邻居节点 $\textit{nxt}$,并将 $\textit{cloned}$ 的邻居节点列表中加入 $\text{dfs}(nxt)$。
104
+ - 最后返回 $\textit{cloned}$。
105
+
106
+ 在主函数中,我们返回 $\text{dfs}(node)$。
107
+
108
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是节点的数量。
96
109
97
110
<!-- tabs:start -->
98
111
@@ -107,23 +120,24 @@ class Node:
107
120
self.neighbors = neighbors if neighbors is not None else []
108
121
"""
109
122
123
+ from typing import Optional
110
124
111
- class Solution :
112
- def cloneGraph (self , node : ' Node' ) -> ' Node' :
113
- visited = defaultdict()
114
125
115
- def clone (node ):
126
+ class Solution :
127
+ def cloneGraph (self , node : Optional[" Node" ]) -> Optional[" Node" ]:
128
+ def dfs (node ):
116
129
if node is None :
117
130
return None
118
- if node in visited:
119
- return visited[node]
120
- c = Node(node.val)
121
- visited[node] = c
122
- for e in node.neighbors:
123
- c.neighbors.append(clone(e))
124
- return c
125
-
126
- return clone(node)
131
+ if node in g:
132
+ return g[node]
133
+ cloned = Node(node.val)
134
+ g[node] = cloned
135
+ for nxt in node.neighbors:
136
+ cloned.neighbors.append(dfs(nxt))
137
+ return cloned
138
+
139
+ g = defaultdict()
140
+ return dfs(node)
127
141
```
128
142
129
143
#### Java
@@ -150,21 +164,25 @@ class Node {
150
164
*/
151
165
152
166
class Solution {
153
- private Map<Node , Node > visited = new HashMap<> ();
167
+ private Map<Node , Node > g = new HashMap<> ();
154
168
155
169
public Node cloneGraph (Node node ) {
170
+ return dfs(node);
171
+ }
172
+
173
+ private Node dfs (Node node ) {
156
174
if (node == null ) {
157
175
return null ;
158
176
}
159
- if (visited . containsKey (node)) {
160
- return visited . get(node);
161
- }
162
- Node clone = new Node (node. val );
163
- visited . put(node, clone);
164
- for ( Node e : node . neighbors) {
165
- clone . neighbors . add(cloneGraph(e));
177
+ Node cloned = g . get (node);
178
+ if (cloned == null ) {
179
+ cloned = new Node (node . val);
180
+ g . put (node, cloned );
181
+ for ( Node nxt : node . neighbors) {
182
+ cloned . neighbors. add(dfs(nxt));
183
+ }
166
184
}
167
- return clone ;
185
+ return cloned ;
168
186
}
169
187
}
170
188
```
@@ -195,16 +213,23 @@ public:
195
213
196
214
class Solution {
197
215
public:
198
- unordered_map<Node* , Node* > visited;
199
-
200
216
Node* cloneGraph(Node* node) {
201
- if (!node) return nullptr;
202
- if (visited.count(node)) return visited[node];
203
- Node* clone = new Node(node->val);
204
- visited[node] = clone;
205
- for (auto& e : node->neighbors)
206
- clone->neighbors.push_back(cloneGraph(e));
207
- return clone;
217
+ unordered_map<Node* , Node* > g;
218
+ auto dfs = [ &] (this auto&& dfs, Node* node) -> Node* {
219
+ if (!node) {
220
+ return nullptr;
221
+ }
222
+ if (g.contains(node)) {
223
+ return g[ node] ;
224
+ }
225
+ Node* cloned = new Node(node->val);
226
+ g[ node] = cloned;
227
+ for (auto& nxt : node->neighbors) {
228
+ cloned->neighbors.push_back(dfs(nxt));
229
+ }
230
+ return cloned;
231
+ };
232
+ return dfs(node);
208
233
}
209
234
};
210
235
```
@@ -221,99 +246,142 @@ public:
221
246
*/
222
247
223
248
func cloneGraph(node *Node) *Node {
224
- visited := map [*Node]*Node{}
225
- var clone func (node *Node) *Node
226
- clone = func (node *Node) *Node {
249
+ g := map[*Node]*Node{}
250
+ var dfs func(node *Node) *Node
251
+ dfs = func(node *Node) *Node {
227
252
if node == nil {
228
253
return nil
229
254
}
230
- if _ , ok := visited [node]; ok {
231
- return visited[node]
255
+ if n , ok := g [node]; ok {
256
+ return n
232
257
}
233
- c := &Node{node.Val , []*Node{}}
234
- visited [node] = c
235
- for _ , e := range node.Neighbors {
236
- c .Neighbors = append (c .Neighbors , clone (e ))
258
+ cloned := &Node{node.Val, []*Node{}}
259
+ g [node] = cloned
260
+ for _, nxt := range node.Neighbors {
261
+ cloned .Neighbors = append(cloned .Neighbors, dfs(nxt ))
237
262
}
238
- return c
263
+ return cloned
239
264
}
240
-
241
- return clone (node)
265
+ return dfs(node)
242
266
}
243
267
```
244
268
245
269
#### TypeScript
246
270
247
271
``` ts
248
272
/**
249
- * Definition for Node .
250
- * class Node {
273
+ * Definition for _Node .
274
+ * class _Node {
251
275
* val: number
252
- * neighbors: Node[]
253
- * constructor(val?: number, neighbors?: Node[]) {
276
+ * neighbors: _Node[]
277
+ *
278
+ * constructor(val?: number, neighbors?: _Node[]) {
254
279
* this.val = (val===undefined ? 0 : val)
255
280
* this.neighbors = (neighbors===undefined ? [] : neighbors)
256
281
* }
257
282
* }
283
+ *
258
284
*/
259
285
260
- function cloneGraph(node : Node | null ): Node | null {
261
- if (node == null ) return null ;
262
-
263
- const visited = new Map ();
264
- visited .set (node , new Node (node .val ));
265
- const queue = [node ];
266
- while (queue .length ) {
267
- const cur = queue .shift ();
268
- for (let neighbor of cur .neighbors || []) {
269
- if (! visited .has (neighbor )) {
270
- queue .push (neighbor );
271
- const newNeighbor = new Node (neighbor .val , []);
272
- visited .set (neighbor , newNeighbor );
273
- }
274
- const newNode = visited .get (cur );
275
- newNode .neighbors .push (visited .get (neighbor ));
286
+ function cloneGraph(node : _Node | null ): _Node | null {
287
+ const g: Map <_Node , _Node > = new Map ();
288
+ const dfs = (node : _Node | null ): _Node | null => {
289
+ if (! node ) {
290
+ return null ;
276
291
}
277
- }
278
- return visited .get (node );
292
+ if (g .has (node )) {
293
+ return g .get (node );
294
+ }
295
+ const cloned = new _Node (node .val );
296
+ g .set (node , cloned );
297
+ for (const nxt of node .neighbors ) {
298
+ cloned .neighbors .push (dfs (nxt ));
299
+ }
300
+ return cloned ;
301
+ };
302
+ return dfs (node );
279
303
}
280
304
```
281
305
306
+ #### JavaScript
307
+
308
+ ``` js
309
+ /**
310
+ * // Definition for a _Node.
311
+ * function _Node(val, neighbors) {
312
+ * this.val = val === undefined ? 0 : val;
313
+ * this.neighbors = neighbors === undefined ? [] : neighbors;
314
+ * };
315
+ */
316
+
317
+ /**
318
+ * @param {_Node} node
319
+ * @return {_Node}
320
+ */
321
+ var cloneGraph = function (node ) {
322
+ const g = new Map ();
323
+ const dfs = node => {
324
+ if (! node) {
325
+ return null ;
326
+ }
327
+ if (g .has (node)) {
328
+ return g .get (node);
329
+ }
330
+ const cloned = new _Node (node .val );
331
+ g .set (node, cloned);
332
+ for (const nxt of node .neighbors ) {
333
+ cloned .neighbors .push (dfs (nxt));
334
+ }
335
+ return cloned;
336
+ };
337
+ return dfs (node);
338
+ };
339
+ ```
340
+
282
341
#### C#
283
342
284
343
``` cs
285
- using System .Collections .Generic ;
344
+ /*
345
+ // Definition for a Node.
346
+ public class Node {
347
+ public int val;
348
+ public IList<Node> neighbors;
349
+
350
+ public Node() {
351
+ val = 0;
352
+ neighbors = new List<Node>();
353
+ }
354
+
355
+ public Node(int _val) {
356
+ val = _val;
357
+ neighbors = new List<Node>();
358
+ }
359
+
360
+ public Node(int _val, List<Node> _neighbors) {
361
+ val = _val;
362
+ neighbors = _neighbors;
363
+ }
364
+ }
365
+ */
286
366
287
367
public class Solution {
288
368
public Node CloneGraph (Node node ) {
289
- if (node == null ) return null ;
290
- var dict = new Dictionary <int , Node >();
291
- var queue = new Queue <Node >();
292
- queue .Enqueue (CloneVal (node ));
293
- dict .Add (node .val , queue .Peek ());
294
- while (queue .Count > 0 )
295
- {
296
- var current = queue .Dequeue ();
297
- var newNeighbors = new List <Node >(current .neighbors .Count );
298
- foreach (var oldNeighbor in current .neighbors )
299
- {
300
- Node newNeighbor ;
301
- if (! dict .TryGetValue (oldNeighbor .val , out newNeighbor ))
302
- {
303
- newNeighbor = CloneVal (oldNeighbor );
304
- queue .Enqueue (newNeighbor );
305
- dict .Add (newNeighbor .val , newNeighbor );
306
- }
307
- newNeighbors .Add (newNeighbor );
369
+ var g = new Dictionary <Node , Node >();
370
+ Node Dfs (Node n ) {
371
+ if (n == null ) {
372
+ return null ;
373
+ }
374
+ if (g .ContainsKey (n )) {
375
+ return g [n ];
308
376
}
309
- current .neighbors = newNeighbors ;
377
+ var cloned = new Node (n .val );
378
+ g [n ] = cloned ;
379
+ foreach (var neighbor in n .neighbors ) {
380
+ cloned .neighbors .Add (Dfs (neighbor ));
381
+ }
382
+ return cloned ;
310
383
}
311
- return dict [node .val ];
312
- }
313
-
314
- private Node CloneVal (Node node )
315
- {
316
- return new Node (node .val , new List <Node >(node .neighbors ));
384
+ return Dfs (node );
317
385
}
318
386
}
319
387
```
0 commit comments