图克隆的含义
图克隆是指在开辟另一块内存,去存储一个与原图结构完全一样的图。
思路
- 图由点和边构成
- 先找到所有点,在新内存中存储下来
- 在找的过程中还要存储边
- 把所有的边复制,之后return
- 回到开头, 最开始只知道一个点和该点的相邻关系,还知道图是联通的
- 上述问题是给一个点,找到和他联通的其他所有点,这类问题被称为连通块问题。连通块问题可以用BFS也可以用DFS,最好用BFS(能用BFS就不要用DFS)
- BFS做连通块问题不需要分层遍历,只需要一层循环就可以,不需要中间的For循环
程序的结构(重要)
分为三部分:
- 用BFS找到所有点
- 利用dict,在新旧节点之间建立一个关系
- 复制所有的边
写程序不要相互嵌套要解耦合,以上三步要并行!!!
克隆图可能遇到的情况
- BFS里再出列的时候添加visited会导致数据重复进入代码如下
def getNodes(self, node):
queque = deque([node])
#visited = set([node])
while queque:
head = queque.popleft()
visited.add(head)#错误代码处
for neighbor in head.neighbors:
if neighbor not in visited:
#visited.add(neighbor)
queque.append(neightbor)
return visited
再上述位置将head加入visited的问题是会导致有些节点重复进入队列中。
图中E出现两次,而且随后的层会出现雪崩效应,不断地翻倍重复,虽然BFS最后会出结果,结果也是对的,但是时间复杂度会多出很多。
解决办法:visited和queque同时添加
完整答案:
"""
class UndirectedGraphNode:
def __init__(self, x):
self.label = x
self.neighbors = []
"""
from collections import deque
class Solution:
"""
@param node: A undirected graph node
@return: A undirected graph node
"""
def cloneGraph(self, node):
# write your code here
root = node
if node is None:
return node
#在旧图中找到所有点
nodes = self.find_all_nodes(node)
# 创建一个字典,把取出来的点与旧图中点创建一个映射关系
mapping = {}
for node in nodes:
mapping[node] = UndirectedGraphNode(node.label)
#将边复制过去
for node in nodes:
new_node = mapping[node]
for neighbor in node.neighbors:
new_neighbors = mapping[neighbor]
new_node.neighbors.append(new_neighbors)
return mapping[root]
def find_all_nodes(self, node):
queque = deque([node])
visited = set([node])
while queque:
head = queque.popleft()
for neighbor in head.neighbors:
if neighbor not in visited:
visited.add(neighbor)
queque.append(neighbor)
return visited
概念理清
- 无向图:互为邻居
- 图的构成: 顶点和边 G = <V, E>
vertex, edge - 解耦合:能分开干的事情就分开干