LeetCode – Clone Graph (Java)

Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors.

Java Solution 1

In this solution,

• a queue is used to do breath first traversal,
• and a map is used to store the visited nodes. It is the map between original node and copied node.

It would be helpful if you draw a diagram and visualize the problem.

```/** * 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;   LinkedList<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>(); HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode,UndirectedGraphNode>();   UndirectedGraphNode newHead = new UndirectedGraphNode(node.label);   queue.add(node); map.put(node, newHead);   while(!queue.isEmpty()){ UndirectedGraphNode curr = queue.pop(); ArrayList<UndirectedGraphNode> currNeighbors = curr.neighbors;   for(UndirectedGraphNode aNeighbor: currNeighbors){ if(!map.containsKey(aNeighbor)){ UndirectedGraphNode copy = new UndirectedGraphNode(aNeighbor.label); map.put(aNeighbor,copy); map.get(curr).neighbors.add(copy); queue.add(aNeighbor); }else{ map.get(curr).neighbors.add(map.get(aNeighbor)); } }   } return newHead; } }```

Java Solution 2

```public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { if(node == null) return null;   LinkedList<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>();   HashMap<UndirectedGraphNode,UndirectedGraphNode> map = new HashMap<UndirectedGraphNode,UndirectedGraphNode>();   queue.offer(node); while(!queue.isEmpty()){ UndirectedGraphNode top = queue.poll(); map.put(top, new UndirectedGraphNode(top.label));   for(UndirectedGraphNode n: top.neighbors){ if(!map.containsKey(n)) queue.offer(n); } }   queue.offer(node); HashSet<UndirectedGraphNode> set = new HashSet<UndirectedGraphNode>(); set.add(node);   while(!queue.isEmpty()){ UndirectedGraphNode top = queue.poll(); for(UndirectedGraphNode n: top.neighbors){ if(!set.contains(n)){ queue.offer(n); set.add(n); } map.get(top).neighbors.add(map.get(n)); } }   return map.get(node); }```
Category >> Algorithms
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
```<pre><code>
String foo = "bar";
</code></pre>
```
• Rishabh Jain

What would be the time complexity?

• Milan

A DFS with alreadyAvailable map that stores (label,new node)
And if node is present in map, use it else create a new node and put in map.
``` public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { if (node == null) return node; Map alreadyAvailable = new HashMap(); return cloneGraphHelper(node,alreadyAvailable); } private UndirectedGraphNode cloneGraphHelper(UndirectedGraphNode node, Map alreadyAvailable) { if ( alreadyAvailable.containsKey(node.label) ) return alreadyAvailable.get(node.label); UndirectedGraphNode returnNode = new UndirectedGraphNode(node.label); alreadyAvailable.put(node.label,returnNode); for(UndirectedGraphNode N: node.neighbors) returnNode.neighbors.add(cloneGraphHelper(N,alreadyAvailable)); return returnNode; } ```

• gowtham Bk

Why should it be bfs ? why not dfs??

• rashmibrahma

import java.util.HashSet;

import java.util.Set;

public class CloneGraph {

public static UndirectedGraphNode cloneGraph(UndirectedGraphNode root1) {

if(root1==null){

return null;

}

UndirectedGraphNode root2;

Set visited=new HashSet();

root2=cloneGraph(root1, visited);

return root2;

}

private static UndirectedGraphNode cloneGraph(UndirectedGraphNode root1, Set visited){

UndirectedGraphNode root2=new UndirectedGraphNode(root1.label);

for(UndirectedGraphNode node:root1.neighbors){

if(!visited.contains(node.label)){

cloneGraph(node, visited);

}

}

return root2;

}

}

• Wayne

import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

public class Solution {

public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {

if (node == null) {

return null;

}

HashMap hasProcessed

= new HashMap();

return cloneGraph(node, hasProcessed);

}

private UndirectedGraphNode cloneGraph(UndirectedGraphNode node,

HashMap hasProcessed) {

UndirectedGraphNode newNode = new UndirectedGraphNode(node.label);

hasProcessed.put(node, newNode);

for (UndirectedGraphNode next : node.neighbors) {

if (hasProcessed.get(next) == null) {

} else {

}

}

return newNode;

}

}

• Howard

Great code. I just wonder whether it should be queue.poll( ), instead of queue.pop( )?

• Yoonsoo Kim

How about the following algorithm in C++? I don’t think we need to use BFS when copying a whole graph. A whole graph can’t be represented by a single node but by a list of node. So I think the following approach works too. The most important thing to clone a whole graph is using hash map between original node and cloned node, not the BFS.

struct node {
int v;
vector E;
node(int v) : v(v) {}
};

auto clone_graph = [](const vector& G) {
vector retG(G.size(), nullptr);
unordered_map node_map;
for (size_t i = 0; i v };
retG[i]->E.resize(G[i]->E.size());
node_map[G[i]] = retG[i];
}

for (size_t i = 0; i < retG.size(); ++i) {
for (size_t j = 0; j E.size(); ++j) {
retG[i]->E[j] = node_map[G[i]->E[j]];
}
}

return retG;
};

Here is another approach which is using BFS.

auto clone_graph2 = [](const vector& G) {
unordered_map cloned;
function impl = [&](node* o) {
queue q;
cloned[o] = new node(o->v);
cloned[o]->E.resize(o->E.size());
q.push(o);

while (!q.empty()) {
auto n = q.front();
q.pop();
for (size_t i = 0; i E.size(); ++i) {
if (cloned.find(n->E[i]) == cloned.end()) {
q.push(n->E[i]);
cloned[n->E[i]] = new node(n->E[i]->v);
cloned[n->E[i]]->E.resize(n->E[i]->E.size());
}
cloned[n]->E[i] = cloned[n->E[i]];
}
}

return cloned[o];
};

vector retG(G.size(), nullptr);
for (size_t i = 0; i < retG.size(); ++i) {
retG[i] = cloned.find(G[i]) == cloned.end() ? impl(G[i]) : cloned[G[i]];
}

return retG;
};

I prefer the first approach for its simplicity

• ryanlr

``` /** * Definition for undirected graph. * class UndirectedGraphNode { * int label; * List neighbors; * UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList(); } * }; */ public class Solution { private Map marked = new HashMap(); public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { if (node==null) return null; UndirectedGraphNode result = new UndirectedGraphNode(node.label); marked.put(node.label, result); for (int i=0; i<node.neighbors.size(); i++) { UndirectedGraphNode toClone = node.neighbors.get(i); UndirectedGraphNode neighbor; if (!marked.containsKey(toClone.label)) { neighbor = cloneGraph(toClone); } else { neighbor = marked.get(toClone.label); } result.neighbors.add(neighbor); } return result; } } ```