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 – DFS

HashMap<Node, Node> map = new HashMap<>();
public Node cloneGraph(Node node) {
    map.put(node, new Node(node.val, new ArrayList<>()));
 
    for(Node neighbor: node.neighbors){
        if(map.containsKey(neighbor)){
            map.get(node).neighbors.add(map.get(neighbor)); 
        }else{
            map.get(node).neighbors.add(cloneGraph(neighbor));
        }
    }
 
    return map.get(node);
}

Java Solution 2 – BFS

public Node cloneGraph(Node node) {
    Map<Node, Node> map = new HashMap<>();
    Queue<Node> queue = new ArrayDeque<>();
 
    queue.offer(node);
    map.put(node, new Node(node.val, new ArrayList<>()));
    while (!queue.isEmpty()) {
        Node h = queue.poll();
 
        for (Node neighbor : h.neighbors) {
            if (!map.containsKey(neighbor)) {
                map.put(neighbor, new Node(neighbor.val, new ArrayList<>()));
                queue.offer(neighbor);
            }
            map.get(h).neighbors.add(map.get(neighbor));
        }
    }
 
    return map.get(node);
}

10 thoughts on “LeetCode – Clone Graph (Java)”

  1. The Time complexity for cloning the graph is O(V+E) and thats because we
    shall be traversing each vertex of the graph from the Queue and then
    visiting each edge E atleast once.

  2. 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;
    }

  3. 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){

    visited.add(root1.label);

    UndirectedGraphNode root2=new UndirectedGraphNode(root1.label);

    for(UndirectedGraphNode node:root1.neighbors){

    root2.neighbors.add(node);

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

    cloneGraph(node, visited);

    }

    }

    return root2;

    }

    }

  4. 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) {

    newNode.neighbors.add(cloneGraph(next, hasProcessed));

    } else {

    newNode.neighbors.add(hasProcessed.get(next));

    }

    }

    return newNode;

    }

    }

  5. 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

  6. Thanks X Wang!

    I used a modified depth first search

    /**

    * 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;

    }

    }

Leave a Comment