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 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
/ \
\_/
Solution1:遞歸 DFS + hashmap
思路:
Example:
1
/ \
0 --- 2 --
| |
---
(1)隨著DFS遍歷src_Graph激况,對每一個(gè)結(jié)點(diǎn)src_node挡逼,clone一個(gè)cloned_node晤硕,
然后對src_node的src_node_neighbor結(jié)點(diǎn)們遞歸重復(fù)相同的clone過程 并將cloned_node_neighbors link到cloned_node中。
(2)在遍歷的過程中佑稠,為避免重復(fù)clone,將已經(jīng)cloned的結(jié)點(diǎn)保存到hashmap中, src_node -> cloned_node埃脏,
這樣一來在遍歷中對于src_node若在map中已經(jīng)存在,則map.get(src_node)即get出已經(jīng)clone過的cloned_node,直接link(避免新建再clone)揽惹。
(3)依照題意,Nodes are labeled uniquely四康,所以此題map其實(shí)可以是src_node_label -> cloned_node_label搪搏,
但為了滿足若不同nodes的label相同的情況,這里map是src_node -> cloned_node
(4)另外闪金,遍歷方式也可以是BFS疯溺,利用queue實(shí)現(xiàn),其他過程不變哎垦。
Time Complexity: O(N) Space Complexity: O(N)
Solution2:stack DFS + hashmap
思路一致囱嫩,用stack使得訪問順序不同,深度優(yōu)先
Solution3:queue BFS + hashmap (not finished)
思路一致漏设,用queue使得訪問順序不同墨闲,廣度優(yōu)先
Solution1 Code:
public class Solution {
private HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>();
public UndirectedGraphNode cloneGraph(UndirectedGraphNode src_node) {
return clone(src_node);
}
private UndirectedGraphNode clone (UndirectedGraphNode src_node) {
if(src_node == null)
return null;
if(map.containsKey(src_node))
return map.get(src_node);
//clone clone_node from src_node
UndirectedGraphNode cloned_node = new UndirectedGraphNode(src_node.label);
map.put(src_node, cloned_node);
for(UndirectedGraphNode src_node_neighbor: src_node.neighbors) {
cloned_node.neighbors.add(clone(src_node_neighbor));
}
return cloned_node;
}
}
Solution2 Code:
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) return null;
HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap(); // src_node -> cloned_node
Stack<UndirectedGraphNode> stack = new Stack<UndirectedGraphNode>(); // for DfS
// first node
UndirectedGraphNode first_cloned_node = new UndirectedGraphNode(node.label);
map.put(node, first_cloned_node); //add first node to HashMap
stack.push(node);
while (!stack.isEmpty()) {
UndirectedGraphNode src_node = stack.pop();
UndirectedGraphNode cloned_node = map.get(src_node);
for(UndirectedGraphNode neighbor : src_node.neighbors) {
UndirectedGraphNode cloned_neighbor;
if(map.containsKey(neighbor)) {
// already visited
cloned_neighbor = map.get(neighbor);
}
else {
// first time visit
cloned_neighbor = new UndirectedGraphNode(neighbor.label);
map.put(neighbor, cloned_neighbor);
stack.push(neighbor);
}
cloned_node.neighbors.add(cloned_neighbor);
}
}
return first_cloned_node;
}
}
Solution3 Code:
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) return null;
HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap(); // src_node -> cloned_node
Queue<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>(); // for BfS
// first node
UndirectedGraphNode first_cloned_node = new UndirectedGraphNode(node.label);
map.put(node, first_cloned_node); //add first node to HashMap
queue.offer(node);
while (!queue.isEmpty()) {
UndirectedGraphNode src_node = queue.poll();
UndirectedGraphNode cloned_node = map.get(src_node);
for(UndirectedGraphNode neighbor : src_node.neighbors) {
UndirectedGraphNode cloned_neighbor;
if(map.containsKey(neighbor)) {
// already visited
cloned_neighbor = map.get(neighbor);
}
else {
// first time visit
cloned_neighbor = new UndirectedGraphNode(neighbor.label);
map.put(neighbor, cloned_neighbor);
queue.add(neighbor);
}
cloned_node.neighbors.add(cloned_neighbor);
}
}
return first_cloned_node;
}
}
Tag_Round1 Code:
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if(node == null) return null;
Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>();
UndirectedGraphNode copy_node = new UndirectedGraphNode(node.label);
map.put(node, copy_node);
dfs_clone(node, map);
return copy_node;
}
private void dfs_clone(UndirectedGraphNode node, Map<UndirectedGraphNode, UndirectedGraphNode> map) {
UndirectedGraphNode copy_node = map.get(node);
for(int i = 0; i < node.neighbors.size(); i++) {
UndirectedGraphNode next = node.neighbors.get(i);
if(!map.containsKey(next)) { // unvisited
UndirectedGraphNode copy_next = new UndirectedGraphNode(next.label);
map.put(next, copy_next);
dfs_clone(next, map);
}
UndirectedGraphNode copy_next = map.get(next);
copy_node.neighbors.add(copy_next);
}
}
}