# 137.克隆图

``````   1
/ \
/   \
0 --- 2
/ \
\_/
``````

#### 代码

1. 3steps
``````/**
* Definition for undirected graph.
* class UndirectedGraphNode {
*     int label;
*     ArrayList<UndirectedGraphNode> neighbors;
*     UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
* };
*/
public class Solution {
/**
* @param node: A undirected graph node
* @return: A undirected graph node
*/
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) {
return node;
}

// use bfs algorithm to traverse the graph and get all nodes.
ArrayList<UndirectedGraphNode> nodes = getNodes(node);

// copy nodes, store the old->new mapping information in a hash map
HashMap<UndirectedGraphNode, UndirectedGraphNode> mapping = new HashMap<>();
for (UndirectedGraphNode n : nodes) {
// 创建hashmap将原图和新图之间结点对应关系存在hashmap中
mapping.put(n, new UndirectedGraphNode(n.label));

}

// copy neighbors(edges)
for (UndirectedGraphNode n : nodes) {
// 复制的新的结点,不能写newNode = n这样复制的是引用，我们需要的是deep copy
UndirectedGraphNode newNode = mapping.get(n);
// neighbors是定义好的存储整型下标的数组
for (UndirectedGraphNode neighbor : n.neighbors) {
// 复制相邻结点，复制相邻结点和复制的结点建立边的关系
UndirectedGraphNode newNeighbor = mapping.get(neighbor);
}
}

// 从输入的结点开始逐渐返回图中每个结点对应的信息
return mapping.get(node);
}

// 用bfs由点到面得到所有结点信息，返回一个包含所有结点的数组
private ArrayList<UndirectedGraphNode> getNodes(UndirectedGraphNode node) {
HashSet<UndirectedGraphNode> set = new HashSet<>();

queue.offer(node);
// bfs利用队列来控制遍历图中结点的顺序
while (!queue.isEmpty()) {
for (UndirectedGraphNode neighbor : head.neighbors) {
if(!set.contains(neighbor)){
queue.offer(neighbor);
}
}
}

// 所有结点都已添加到 set，此处用深度拷贝是因为外边要用ArrayList，而此处是hashset
return new ArrayList<UndirectedGraphNode>(set);
}
}
``````
1. two steps
``````/**
* Definition for undirected graph.
* class UndirectedGraphNode {
*     int label;
*     ArrayList<UndirectedGraphNode> neighbors;
*     UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
* };
*/
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) {
return null;
}

ArrayList<UndirectedGraphNode> nodes = new ArrayList<UndirectedGraphNode>();
HashMap<UndirectedGraphNode, UndirectedGraphNode> map
= new HashMap<UndirectedGraphNode, UndirectedGraphNode>();

// clone nodes
map.put(node, new UndirectedGraphNode(node.label));

int start = 0;
while (start < nodes.size()) {
for (int i = 0; i < head.neighbors.size(); i++) {
if (!map.containsKey(neighbor)) {
map.put(neighbor, new UndirectedGraphNode(neighbor.label));
}
}
}

// clone neighbors
for (int i = 0; i < nodes.size(); i++) {
UndirectedGraphNode newNode = map.get(nodes.get(i));
for (int j = 0; j < nodes.get(i).neighbors.size(); j++) {
}
}

return map.get(node);
}
}
``````
1. Non-Recursion DFS
``````/**
* Definition for undirected graph.
* class UndirectedGraphNode {
*     int label;
*     ArrayList<UndirectedGraphNode> neighbors;
*     UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
* };
*/
class StackElement {
public UndirectedGraphNode node;
public int neighborIndex;
public StackElement(UndirectedGraphNode node, int neighborIndex) {
this.node = node;
this.neighborIndex = neighborIndex;
}
}

public class Solution {
/**
* @param node: A undirected graph node
* @return: A undirected graph node
*/
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) {
return node;
}

// use dfs algorithm to traverse the graph and get all nodes.
ArrayList<UndirectedGraphNode> nodes = getNodes(node);

// copy nodes, store the old->new mapping information in a hash map
HashMap<UndirectedGraphNode, UndirectedGraphNode> mapping = new HashMap<>();
for (UndirectedGraphNode n : nodes) {
mapping.put(n, new UndirectedGraphNode(n.label));
}

// copy neighbors(edges)
for (UndirectedGraphNode n : nodes) {
UndirectedGraphNode newNode = mapping.get(n);
for (UndirectedGraphNode neighbor : n.neighbors) {
UndirectedGraphNode newNeighbor = mapping.get(neighbor);
}
}

return mapping.get(node);
}

private ArrayList<UndirectedGraphNode> getNodes(UndirectedGraphNode node) {
Stack<StackElement> stack = new Stack<StackElement>();
HashSet<UndirectedGraphNode> set = new HashSet<>();
stack.push(new StackElement(node, -1));

while (!stack.isEmpty()) {
StackElement current = stack.peek();
current.neighborIndex++;
// there is no more neighbor to traverse for the current node
if (current.neighborIndex == current.node.neighbors.size()) {
stack.pop();
continue;
}

UndirectedGraphNode neighbor = current.node.neighbors.get(
current.neighborIndex
);
// check if we visited this neighbor before
if (set.contains(neighbor)) {
continue;
}

stack.push(new StackElement(neighbor, -1));
}

return new ArrayList<UndirectedGraphNode>(set);
}
}``````

### 推荐阅读更多精彩内容

• Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具（例如配置管理，服务发现，断路器，智...
卡卡罗2017阅读 128,965评论 18 137
• Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
passiontim阅读 164,151评论 24 696
• 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪：刷leetcod...
土汪阅读 12,162评论 0 33
• 原题 克隆一张无向图，图中的每个节点包含一个 label 和一个表 neighbors。你的程序需要返回一个经过深...
Jason_Yuan阅读 1,634评论 0 0
• 1 序 2016年6月25日夜，帝都，天下着大雨，拖着行李箱和同学在校门口照了最后一张合照，搬离寝室打车去了提前租...
RichardJieChen阅读 4,556评论 0 12
• 婆婆婆婆家 我是信工姓名哦 我是无所谓心鱼死网破婆婆羽绒口蘑透明木木木哦咯做清明 鱼死网破送你孙我公公 鱼死网破咯...
Elephant037阅读 227评论 0 0
• 家乡里的山多，它们都有一个很朴实的名字，就像大山里的父母给儿女们起名一样，都是嘴边那些最好叫、最直白的字眼。杨芳林...
圆圆2408阅读 83评论 0 2