Clone an undirected graph. Each node in the graph contains a label
and a list of its neighbors
.
OJ's undirected graph serialization:
Nodes are labeled uniquely.
We use#
as a separator for each node, and ,
as a separator for node label and each neighbor of the node.
As an example, consider the serialized graph {0,1,2#1,2#2,2}
.
The graph has a total of three nodes, and therefore contains three parts as separated by #
.
- First node is labeled as
0
. Connect node0
to both nodes1
and2
. - Second node is labeled as
1
. Connect node1
to node2
. - Third node is labeled as
2
. Connect node2
to node2
(itself), thus forming a self-cycle.
Visually, the graph looks like the following:
1 / / 0 --- 2 / \_/
这题目的是clone 图,那么遍历原图建立新图的过程不可避免,用BFS或者DFS都可以。但是一点是如何建立将原图之间的结点链接映射到新图当中,old_node,new_node这样的键值对不可避免,需要用到一个hashmap,另外无论DFS还是BFS都需要判断当前的点有没有重复遍历,所以hashmap一箭双雕,
即一个查原图点有没有遍历过,另外对已经遍历的点,建立旧点和新点的映射。值得注意的是,这题给出的图的定义比较坑,即临接边只会出现在其中一个顶点的临接表中,另外一个不会出现。所以处理当前点的邻居时,不管该邻居之前有没有被遍历过,链接都需要建立。
BFS代码如下:
class Solution(object): def cloneGraph(self, node): """ :type node: UndirectedGraphNode :rtype: UndirectedGraphNode """ if not node: return None map = {} queue = collections.deque() queue.append(node) newNode = UndirectedGraphNode(node.label) map[node] = newNode while queue: oldNode = queue.popleft() for neighbor in oldNode.neighbors: if neighbor not in map: newNode = UndirectedGraphNode(neighbor.label) map[neighbor] = newNode queue.append(neighbor) map[oldNode].neighbors.append(map[neighbor]) return map[node]
DFS非递归遍历如下:
class Solution(object): def cloneGraph(self, node): """ :type node: UndirectedGraphNode :rtype: UndirectedGraphNode """ if not node: return None map = {} stack = [node] map[node.label] = UndirectedGraphNode(node.label) while stack: cur = stack.pop() for neighbor in cur.neighbors: if neighbor.label not in map: map[neighbor.label] = UndirectedGraphNode(neighbor.label) stack.append(neighbor) map[cur.label].neighbors.append(map[neighbor.label]) return map[node.label]
DFS递归遍历:
class Solution(object): def cloneGraph(self, node): """ :type node: UndirectedGraphNode :rtype: UndirectedGraphNode """ if not node: return None map = {} map[node] = UndirectedGraphNode(node.label) self.dfs(node, map) return map[node] def dfs(self, node, map): for neighbor in node.neighbors: if neighbor not in map: map[neighbor] = UndirectedGraphNode(neighbor.label) self.dfs(neighbor, map) map[node].neighbors.append(map[neighbor])
这三种做法的时间复杂度都是O(V+E),结点入栈或者队列一次,出一次,边也要扫一次,判断。注意这题结点的值都不一样,为了节省空间,可以只使用原结点的值做hashmap的键值。