Clone an undirected graph. Each node in the graph contains a
label
and a list of itsneighbors
.
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
#
.
1. First node is labeled as 0. Connect node 0 to both nodes 1 and 2.
2. Second node is labeled as 1. Connect node 1 to node 2.
3. 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 / \ \_/
简单来说,就是让我们实现克隆一个无向图,克隆的意思是再创造一个一模一样的无向图,需要另外申请内存空间,不能直接原封不动的把输入直接作为结果返回 (/ □ \)
题目描述中使用了邻接链表来表示这个无向图,要克隆这个无向图,我们必定要用到图的搜索,由起点开始,根据原图的边信息来访问原图中的每个结点,同时拷贝这个结点及相关边的信息,即可完成图的克隆。对于图的搜索我们可以使用BFS或DFS,使用BFS要创建一个队列,使用DFS可以使用递归或创建一个栈,这里使用DFS递归求解本题。
需要注意的是,根据边的信息访问到原图中的某一结点,该结点在此之前有可能已经被访问过了,比如对题干例子的第一趟无回退深搜访问路径 0 ——> 1 ——> 2 ——> 2,就已经重复访问了结点2,所以我们需要对访问过的结点进行标记,为了节省空间这里使用HashMap来进行标记。代码如下
/**
* Definition for undirected graph.
* class UndirectedGraphNode {
* int label;
* List<UndirectedGraphNode> neighbors;
* UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
* };
*/
public class Solution {
private HashMap<Integer, UndirectedGraphNode> labelToNode = new HashMap<>();
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
return clone(node);
}
private UndirectedGraphNode clone(UndirectedGraphNode node)
{
if(node == null)
return null;
if (labelToNode.containsKey(node.label)) // 已被访问且拷贝过的结点
return labelToNode.get(node.label);
UndirectedGraphNode copy = new UndirectedGraphNode(node.label); // 没有被访问过的新结点
labelToNode.put(copy.label, copy);
for(UndirectedGraphNode nbr : node.neighbors)
copy.neighbors.add(clone(nbr));
return copy;
}
}