Problem: Clone an undirected graph. Each node in the graph contains a label
and a list of its neighbors
.
Analysis: This problem can be solved using either BFS (queue) or DFS (stack or recursion).
DFS (Recursion):
Input: A graph G and a root v of G
1 procedure DFS(G,v):
2 label v as discovered
3 for all edges from v to w in G.adjacentEdges(v) do
4 if vertex w is not labeled as discovered then
5 recursively call DFS(G,w)
DFS (Stack):
Input: A graph G and a root v of G
1 procedure DFS-iterative(G,v):
2 let S be a stack
3 S.push(v)
4 while S is not empty
5 v ← S.pop()
6 if v is not labeled as discovered:
7 label v as discovered
8 for all edges from v to w in G.adjacentEdges(v) do
9 S.push(w)
BFS (Queue):
Input: A graph G and a root v of G
1 procedure BFS(G,v) isBFS can be used to help find the shortest path.
2 create a queue Q
3 create a set V
4 add v to V
5 enqueue v onto Q
6 while Q is not empty loop
7 t ← Q.dequeue()
8 if t is what we are looking for then
9 return t
10 end if
11 for all edges e in G.adjacentEdges(t) loop
12 u ← G.adjacentVertex(t,e)
13 if u is not in V then
14 add u to V
15 enqueue u onto Q
16 end if
17 end loop
18 end loop
19 return none
20 end BFS
Using the above approaches to solve this problem:
DFS (Recursion):
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) {
return null;
}
Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>();
UndirectedGraphNode root = new UndirectedGraphNode(node.label);
map.put(node, root);
dfs(node, map);
return root;
}
private void dfs(UndirectedGraphNode node, Map<UndirectedGraphNode, UndirectedGraphNode> map) {
if (node == null) { // condition to end recursion
return;
}
for (UndirectedGraphNode neighbor : node.neighbors) {
if (!map.containsKey(neighbor)) { // not visited
UndirectedGraphNode _neighbor = new UndirectedGraphNode(neighbor.label);
map.put(neighbor, _neighbor);
dfs(neighbor, map);
}
map.get(node).neighbors.add(map.get(neighbor));
}
}
}
DFS (Stack):
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) {
return null;
}
UndirectedGraphNode root = new UndirectedGraphNode(node.label);
Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>();
map.put(node, root);
Stack<UndirectedGraphNode> stack = new Stack<>();
stack.push(node);
while (!stack.isEmpty()) {
UndirectedGraphNode tmp = stack.pop();
for (UndirectedGraphNode neighbor : tmp.neighbors) {
if (!map.containsKey(neighbor)) { // not visited
UndirectedGraphNode _neighbor = new UndirectedGraphNode(neighbor.label);
map.put(neighbor, _neighbor);
stack.push(neighbor);
}
map.get(tmp).neighbors.add(map.get(neighbor));
}
}
return root;
}
}
BFS (Queue + Loop):
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) {
return null;
}
UndirectedGraphNode root = new UndirectedGraphNode(node.label);
Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>();
map.put(node, root);
Queue<UndirectedGraphNode> queue = new LinkedList<>();
queue.add(node);
while (!queue.isEmpty()) {
UndirectedGraphNode tmp = queue.poll();
for (UndirectedGraphNode neighbor : tmp.neighbors) {
if (!map.containsKey(neighbor)) { // not visited
UndirectedGraphNode _neighbor = new UndirectedGraphNode(neighbor.label);
map.put(neighbor, _neighbor);
queue.add(neighbor);
}
map.get(tmp).neighbors.add(map.get(neighbor));
}
}
return root;
}
}