Skip to content
Merged
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions graphs/deep_clone_graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
"""
LeetCode 133. Clone Graph
https://leetcode.com/problems/clone-graph/

Given a reference of a node in a connected undirected graph.

Return a deep copy (clone) of the graph.

Each node in the graph contains a value (int) and a list (List[Node]) of its
neighbors.
"""
from dataclasses import dataclass


@dataclass
class Node:
value: int = 0
neighbors: list["Node"] | None = None

def __post_init__(self):
self.neighbors = self.neighbors or []

def __hash__(self):
return id(self)


def clone_graph(node: Node | None) -> Node | None:
"""
This function returns a clone of a connected undirected graph.
>>> clone_graph(Node(1))
Node(value=1, neighbors=[])
>>> clone_graph(Node(1, [Node(2)]))
Node(value=1, neighbors=[Node(value=2, neighbors=[])])
>>> clone = clone_graph(None)
>>> clone is None
True
"""
if not node:
return None

originals_to_clones = {} # map nodes to clones

stack = [node]

while stack:
original = stack.pop()

if original in originals_to_clones:
continue

originals_to_clones[original] = Node(original.value)

if not original.neighbors:
continue

for neighbor in original.neighbors:
stack.append(neighbor)

for original, clone in originals_to_clones.items():
if not original.neighbors:
continue

for neighbor in original.neighbors:
cloned_neighbor = originals_to_clones[neighbor]

if not clone.neighbors:
clone.neighbors = []

clone.neighbors.append(cloned_neighbor)

return originals_to_clones[node]


if __name__ == "__main__":
import doctest

doctest.testmod()