Skip to content

Commit a54078e

Browse files
dbringsedatguzelsemme
authored andcommittedSep 15, 2024
Added algorithm to deeply clone a graph (TheAlgorithms#9765)
* Added algorithm to deeply clone a graph * Fixed file name and removed a function call * Removed nested function and fixed class parameter types * Fixed doctests * bug fix * Added class decorator * Updated doctests and fixed precommit errors * Cleaned up code * Simplified doctest * Added doctests * Code simplification
1 parent bdac186 commit a54078e

File tree

1 file changed

+77
-0
lines changed

1 file changed

+77
-0
lines changed
 

‎graphs/deep_clone_graph.py

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""
2+
LeetCode 133. Clone Graph
3+
https://leetcode.com/problems/clone-graph/
4+
5+
Given a reference of a node in a connected undirected graph.
6+
7+
Return a deep copy (clone) of the graph.
8+
9+
Each node in the graph contains a value (int) and a list (List[Node]) of its
10+
neighbors.
11+
"""
12+
from dataclasses import dataclass
13+
14+
15+
@dataclass
16+
class Node:
17+
value: int = 0
18+
neighbors: list["Node"] | None = None
19+
20+
def __post_init__(self) -> None:
21+
"""
22+
>>> Node(3).neighbors
23+
[]
24+
"""
25+
self.neighbors = self.neighbors or []
26+
27+
def __hash__(self) -> int:
28+
"""
29+
>>> hash(Node(3)) != 0
30+
True
31+
"""
32+
return id(self)
33+
34+
35+
def clone_graph(node: Node | None) -> Node | None:
36+
"""
37+
This function returns a clone of a connected undirected graph.
38+
>>> clone_graph(Node(1))
39+
Node(value=1, neighbors=[])
40+
>>> clone_graph(Node(1, [Node(2)]))
41+
Node(value=1, neighbors=[Node(value=2, neighbors=[])])
42+
>>> clone_graph(None) is None
43+
True
44+
"""
45+
if not node:
46+
return None
47+
48+
originals_to_clones = {} # map nodes to clones
49+
50+
stack = [node]
51+
52+
while stack:
53+
original = stack.pop()
54+
55+
if original in originals_to_clones:
56+
continue
57+
58+
originals_to_clones[original] = Node(original.value)
59+
60+
stack.extend(original.neighbors or [])
61+
62+
for original, clone in originals_to_clones.items():
63+
for neighbor in original.neighbors or []:
64+
cloned_neighbor = originals_to_clones[neighbor]
65+
66+
if not clone.neighbors:
67+
clone.neighbors = []
68+
69+
clone.neighbors.append(cloned_neighbor)
70+
71+
return originals_to_clones[node]
72+
73+
74+
if __name__ == "__main__":
75+
import doctest
76+
77+
doctest.testmod()

0 commit comments

Comments
 (0)
Please sign in to comment.