给定无向连通图中一个节点的引用,返回该图的深拷贝(克隆)。图中的每个节点都包含它的值 val
(Int
) 和其邻居的列表(list[Node]
)。
示例:
输入: {"$id":"1","neighbors":[{"$id":"2","neighbors":[{"$ref":"1"},{"$id":"3","neighbors":[{"$ref":"2"},{"$id":"4","neighbors":[{"$ref":"3"},{"$ref":"1"}],"val":4}],"val":3}],"val":2},{"$ref":"4"}],"val":1} 解释: 节点 1 的值是 1,它有两个邻居:节点 2 和 4 。 节点 2 的值是 2,它有两个邻居:节点 1 和 3 。 节点 3 的值是 3,它有两个邻居:节点 2 和 4 。 节点 4 的值是 4,它有两个邻居:节点 1 和 3 。
提示:
- 节点数介于 1 到 100 之间。
- 无向图是一个简单图,这意味着图中没有重复的边,也没有自环。
- 由于图是无向的,如果节点 p 是节点 q 的邻居,那么节点 q 也必须是节点 p 的邻居。
- 必须将给定节点的拷贝作为对克隆图的引用返回。
代码以及注释:
"""
# Definition for a Node.
class Node:
def __init__(self, val, neighbors):
self.val = val
self.neighbors = neighbors
"""
class Solution:
def cloneGraph(self, node: 'Node') -> 'Node':
if node != None:
d = {}
head = Node(node.val,[])
# 副本结点的neighbors暂时保存原始结点node的各个child
# self.f函数中还需要创建新结点,进行替换
for e in node.neighbors:
head.neighbors.append(e)
d[node] = head
self.f(head, d)
return head
return None
def f(self,head,d):
# d是一个字典,用来保存原始结点 到 对应副本结点的映射
# r用来保存当前函数新创建的副本结点
r = []
for index,e in enumerate(head.neighbors):
# 如果原始结点不在d中,说明该原始结点还不在新图当中
if e not in d:
cur = Node(e.val, [])
for t in e.neighbors:
cur.neighbors.append(t)
# e对应的副本r已经创建,添加映射关系
d[e] = cur
# 跟新新图中当前结点的neighbors
head.neighbors[index] = cur
# 当前for循环宽度优先遍历完之后,
# 遍历新创建的副本结点
r.append(cur)
# 若有原始借点在d中,说明该结点已经存在新图中
else:
head.neighbors[index] = d[e]
# 宽度优先遍历完之后,进入下一层。
for i in r:
self.f(i, d)