Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors.node
We use # as a separator for each node, and , as a separator for node label and each neighbor of the node.ide
return a deep copied graph.code
How we serialize an undirected graph.
Nodes are labeled uniquely.
As an example, consider the serialized graph {0,1,2#1,2#2,2}
.orm
The graph has a total of three nodes, and therefore contains three parts as separated by #.three
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:get
1 / \ / \ 0 --- 2 / \ \_/
開始看這道題目的時候,沒有看懂queue和hashmap的做用。
複製一個無向圖,先分析圖的結構:label
至關於圖結點的value,而neighbors
至關於圖結點的全部next。而後考慮用什麼方式複製:用queue用來標記當前正在複製的或已經複製過的結點cur
,而hashmap用來進行對新建無向圖結點root
進行復制label
和neighbors
的操做。首先,從node
結點開始,放入queue。而後對這個放入queue的結點cur
開始操做:遍歷cur
的全部neighbors
,當前遍歷到的的neighbors
叫作next
。若map中不存在這個點,即沒有被複制過,就在map中複製這個結點next
的label
,同時存入queue以便在下次循環取出並複製其neighbors
;不管map中包不包含這個neighbors
結點next
,都要將next
加入map中對應新建結點root
的neighbors
。當BFS完成,則queue中沒有新的結點了,退出while
循環。返回在map中更新過的root
,結束。
map.get(cur).neighbors.add(map.get(next));
這一句能夠理解爲,在for循環對cur
的neighbors
的遍歷中,先在HashMap裏的root
中創建新結點next
,再將next
放進root
的結點cur
的neighbors
裏。hash
// 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; UndirectedGraphNode root = new UndirectedGraphNode(node.label);//複製根節點 Queue<UndirectedGraphNode> queue = new LinkedList<>(); Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>(); queue.offer(node);//queue放入根結點 map.put(node, root);//map放入根結點和它的複製結點 while (!queue.isEmpty()) { UndirectedGraphNode cur = queue.poll();//取出queue中(同一層)的結點進行BFS for (UndirectedGraphNode n: cur.neighbors) { //對沒有複製過的結點進行復制,並將這個結點放入queue if (!map.containsKey(n)) { map.put(n, new UndirectedGraphNode(n.label)); queue.offer(n); } //鏈接複製結點和複製neighbor結點 map.get(cur).neighbors.add(map.get(n)); } } return root; } }
public class Solution { public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { if (node == null) return node; Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>(); map.put(node, new UndirectedGraphNode(node.label)); //<k, v>: <原結點, 複製結點> Queue<UndirectedGraphNode> queue = new LinkedList<>(); queue.offer(node); //copy過的結點存入queue,以繼續遍歷其neighbor結點 while (!queue.isEmpty()) { UndirectedGraphNode cur = queue.poll(); //取出copy過的結點,繼續複製其全部neighbor結點 for (UndirectedGraphNode neighbor: cur.neighbors) { if (!map.containsKey(neighbor)) { //若結點未複製過,copy後存入queue map.put(neighbor, new UndirectedGraphNode(neighbor.label)); queue.offer(neighbor); } map.get(cur).neighbors.add(map.get(neighbor)); //將每一個copied neighbor存入copied parent node } } return map.get(node); //返回copied根節點 } }
DFSit
public class Solution { public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>(); return cloneNode(node, map); } private UndirectedGraphNode cloneNode(UndirectedGraphNode node, Map<UndirectedGraphNode, UndirectedGraphNode> map) { if (node == null) return node; if (map.containsKey(node)) { return map.get(node); } else { UndirectedGraphNode nodeCopy = new UndirectedGraphNode(node.label); map.put(node, nodeCopy); for (UndirectedGraphNode child : node.neighbors) { nodeCopy.neighbors.add(cloneNode(child, map)); } return nodeCopy; } } }