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,对每一个结点src_node,clone一个cloned_node,
然后对src_node的src_node_neighbor结点们递归重复相同的clone过程 并将cloned_node_neighbors link到cloned_node中。
(2)在遍历的过程中,为避免重复clone,将已经cloned的结点保存到hashmap中, src_node -> cloned_node,
这样一来在遍历中对于src_node若在map中已经存在,则map.get(src_node)即get出已经clone过的cloned_node,直接link(避免新建再clone)。
(3)依照题意,Nodes are labeled uniquely,所以此题map其实可以是src_node_label -> cloned_node_label,
但为了满足若不同nodes的label相同的情况,这里map是src_node -> cloned_node
(4)另外,遍历方式也可以是BFS,利用queue实现,其他过程不变。
Time Complexity: O(N) Space Complexity: O(N)
Solution2:stack DFS + hashmap
思路一致,用stack使得访问顺序不同,深度优先
Solution3:queue BFS + hashmap (not finished)
思路一致,用queue使得访问顺序不同,广度优先
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);
}
}
}