LeetCode Clone Graph Java

LeetCode Problem:

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

leetcode-clone-graph-java

Key to Solve This Problem

  • A queue is used to do breath first traversal.
  • 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.

clone-graph-leetcode-java

/**
 * 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;
    }
}
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>
  • 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){

    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;

    }

    }

  • 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) {

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

    } else {

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

    }

    }

    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

    Thanks for your comment. I want to read your code, can you put your code inside <pre></pre> tags?

  • Henry

    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;

    }

    }