Description
Given the head of a graph, return a deep copy (clone) of the graph. Each node in the graph contains a label (int) and a list (List[UndirectedGraphNode]) of its neighbors. There is an edge between the given node and each of the nodes in its neighbors.
OJ’s undirected graph serialization (so you can understand error output):
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 node 0 to both nodes 1 and 2.
- Second node is labeled as 1. Connect node 1 to node 2.
- Third node is labeled as 2. Connect node 2 to node 2 (itself), thus forming a self-cycle.
Visually, the graph looks like the following:
1
/ \
/ \
0 --- 2
/ \
\_/
Note: The information about the tree serialization is only meant so that you can understand error output if you get a wrong answer. You don’t need to understand the serialization to solve the problem.
分析一
题目的意思是:复制一个graph
- BFS,map;我们先把所有的结点复制一遍,用一个map存储,键为老结点,值为新来的结点。然后宽度遍历其邻居结点,加入队列,加入队列前要判断map是否有重复,重复的忽略。然后我们遍历这个map,复制邻居结点。
代码-BFS
/**
* Definition for undirected graph.
* struct UndirectedGraphNode {
* int label;
* vector<UndirectedGraphNode *> neighbors;
* UndirectedGraphNode(int x) : label(x) {};
* };
*/
class Solution {
public:
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
// 拷贝所有节点, BFS, 并建立一个新节点地址与老节点地址的对应关系
map<UndirectedGraphNode *, UndirectedGraphNode *> mymap;
BFS(node,mymap);
// 更新新节点内部的指针数组
for(map<UndirectedGraphNode *, UndirectedGraphNode *>::iterator iter=mymap.begin();
iter!=mymap.end();iter++){
for(int i=0;i<(iter->first)->neighbors.size();i++){
UndirectedGraphNode * temp=iter->first->neighbors[i];
iter->second->neighbors.push_back(mymap[temp]);
}
}
return mymap[node];
}
private:
void BFS(UndirectedGraphNode * node, map<UndirectedGraphNode *, UndirectedGraphNode *> & mymap){
// 节点无效, 或者节点已经被访问过了
if(node==NULL||mymap.find(node)!=mymap.end()){
return ;
}
// 插入根节点位置
queue<UndirectedGraphNode *> queue1;
queue1.push(node);
while(!queue1.empty()){
// 访问队列中的节点
UndirectedGraphNode *front=queue1.front();
queue1.pop();
UndirectedGraphNode *newNode=new UndirectedGraphNode(front->label);
mymap.insert(make_pair(front,newNode));
// 更新队列
for(int i=0;i<front->neighbors.size();i++){
if(mymap.find(front->neighbors[i])==mymap.end()){
queue1.push(front->neighbors[i]);
}
}
}
}
};
分析二
- DFS的版本,相比于BFS,DFS更简洁一点。
代码-DFS
/**
* Definition for undirected graph.
* struct UndirectedGraphNode {
* int label;
* vector<UndirectedGraphNode *> neighbors;
* UndirectedGraphNode(int x) : label(x) {};
* };
*/
class Solution {
public:
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
unordered_map<int, UndirectedGraphNode*> umap;
return clone(node,umap);
}
UndirectedGraphNode *clone(UndirectedGraphNode *node,unordered_map<int, UndirectedGraphNode*>& umap){
if(!node) return NULL;
if(umap.count(node->label)) return umap[node->label];
UndirectedGraphNode *newNode=new UndirectedGraphNode(node->label);
umap[node->label]=newNode;
for(int i=0;i<node->neighbors.size();i++){
(newNode->neighbors).push_back(clone(node->neighbors[i],umap));
}
return newNode;
}
};
Python实现
思路还是dfs,但是dfs的时候要注意已经创建过的新的节点,所以需要一个hash map来记录。
"""
# Definition for a Node.
class Node:
def __init__(self, val = 0, neighbors = None):
self.val = val
self.neighbors = neighbors if neighbors is not None else []
"""
from typing import Optional
class Solution:
def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
umap = {}
return self.clone(node, umap)
def clone(self, node, umap):
if node is None:
return node
if node.val in umap:
return umap[node.val]
new_node = Node(node.val)
umap[node.val]=new_node
for i in range(len(node.neighbors)):
new_node.neighbors.append(self.clone(node.neighbors[i], umap))
return new_node