zoukankan      html  css  js  c++  java
  • LeetCode: Clone Graph 解题报告

    Clone Graph
    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
             /
             \_/

    Solution 1:

    使用BFS来解决此问题。用一个Queue来记录遍历的节点,遍历原图,并且把复制过的节点与原节点放在MAP中防止重复访问。

    图的遍历有两种方式,BFS和DFS

    这里使用BFS来解本题,BFS需要使用queue来保存neighbors

    但这里有个问题,在clone一个节点时我们需要clone它的neighbors,而邻居节点有的已经存在,有的未存在,如何进行区分?

    这里我们使用Map来进行区分,Map的key值为原来的node,value为新clone的node,当发现一个node未在map中时说明这个node还未被clone,

    将它clone后放入queue中处理neighbors。

    使用Map的主要意义在于充当BFS中Visited数组,它也可以去环问题,例如A--B有条边,当处理完A的邻居node,然后处理B节点邻居node时发现A已经处理过了

    处理就结束,不会出现死循环。

    queue中放置的节点都是未处理neighbors的节点。

    http://www.cnblogs.com/feiling/p/3351921.html

     1 /*
     2         Iteration Solution:
     3     */
     4     public UndirectedGraphNode cloneGraph1(UndirectedGraphNode node) {
     5         if (node == null) {
     6             return null;
     7         }
     8         
     9         UndirectedGraphNode root = null;
    10         
    11         // store the nodes which are cloned.
    12         HashMap<UndirectedGraphNode, UndirectedGraphNode> map = 
    13             new HashMap<UndirectedGraphNode, UndirectedGraphNode>();
    14         
    15         Queue<UndirectedGraphNode> q = new LinkedList<UndirectedGraphNode>();
    16         
    17         q.offer(node);
    18         UndirectedGraphNode rootCopy = new UndirectedGraphNode(node.label);
    19         
    20         // 别忘记这一行啊。orz..
    21         map.put(node, rootCopy);
    22         
    23         // BFS the graph.
    24         while (!q.isEmpty()) {
    25             UndirectedGraphNode cur = q.poll();
    26             UndirectedGraphNode curCopy = map.get(cur);
    27             
    28             // bfs all the childern node.
    29             for (UndirectedGraphNode child: cur.neighbors) {
    30                 // the node has already been copied. Just connect it and don't need to copy.
    31                 if (map.containsKey(child)) {
    32                     curCopy.neighbors.add(map.get(child));
    33                     continue;
    34                 }
    35                 
    36                 // put all the children into the queue.
    37                 q.offer(child);
    38                 
    39                 // create a new child and add it to the parent.
    40                 UndirectedGraphNode childCopy = new UndirectedGraphNode(child.label);
    41                 curCopy.neighbors.add(childCopy);
    42                 
    43                 // Link the new node to the old map.
    44                 map.put(child, childCopy);
    45             }
    46         }
    47         
    48         return rootCopy;        
    49     }
    View Code

    2014.12.30 Redo:

     1 /*
     2         SOLUTION 3: The improved Version.
     3     */
     4     public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
     5         if (node == null) {
     6             return null;
     7         }        
     8         
     9         HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>();
    10         
    11         // BUG 1: can't use queue , should use LinkedList.
    12         Queue<UndirectedGraphNode> q = new LinkedList<UndirectedGraphNode>();
    13         
    14         q.offer(node);
    15         
    16         // copy the root node. and then put it into the map.
    17         UndirectedGraphNode nodeCopy = new UndirectedGraphNode(node.label);
    18         map.put(node, nodeCopy);
    19         
    20         while (!q.isEmpty()) {
    21             UndirectedGraphNode cur = q.poll();
    22             
    23             // get out the copy node. We guarantee that it has been copied. Because we always put it into the map before
    24             // put it into the queue.
    25             UndirectedGraphNode curCopy = map.get(cur);
    26             
    27             // go through all the children node.
    28             // Line 71: java.util.ConcurrentModificationException. use cur instead of curCopy
    29             for (UndirectedGraphNode child: cur.neighbors) {
    30                 
    31                 if (map.containsKey(child)) {
    32                     curCopy.neighbors.add(map.get(child));
    33                 } else {
    34                     // Only add the child into the map when it is not visited.
    35                     q.offer(child);
    36                     
    37                     // BUG 3: forget to add the new node into the map.
    38                     UndirectedGraphNode childCopy = new UndirectedGraphNode(child.label);
    39                     curCopy.neighbors.add(childCopy);
    40                     map.put(child, childCopy);
    41                 }
    42             }
    43         }
    44         
    45         return map.get(node);
    46     }
    View Code

    Solution 2:

    同样的,我们也可以使用递归DFS来解决此题,思路与上图一致,但为了避免重复运算产生死循环。当进入DFS时,如果发现map中已经有了拷贝过的值,直接退出即可。

    题目虽然简单,但主页君仍然考虑了递归的特性使程序简洁。比如:我们拷贝只拷贝根节点,而子节点的拷贝由recursion来完成,这样可以使程序更加简洁。

    注意:要先加入到map,再调用rec ,否则会造成不断地反复拷贝而死循环。

     1 /*
     2         Solution 2: Recursion version.
     3     */
     4     public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
     5         if (node == null) {
     6             return null;
     7         }
     8         
     9         return rec(node, new HashMap<UndirectedGraphNode, UndirectedGraphNode>());
    10     }
    11     
    12     public UndirectedGraphNode rec(UndirectedGraphNode root, HashMap<UndirectedGraphNode, UndirectedGraphNode> map) {
    13         // If it has been copied, just return the copy node from the map.
    14         UndirectedGraphNode rootCopy = map.get(root);
    15         if (rootCopy != null) {
    16             return rootCopy;
    17         }
    18         
    19         // if the root is not copied, create a new one.
    20         rootCopy = new UndirectedGraphNode(root.label);
    21         map.put(root, rootCopy);
    22         
    23         // copy all the child node.
    24         for (UndirectedGraphNode child: root.neighbors) {
    25             // call the recursion to create all the children and add the new children to the copy node.
    26             rootCopy.neighbors.add(rec(child, map));            
    27         }
    28         
    29         return rootCopy;        
    30     }
    View Code

    2014.12.30 Redo:

     1 public UndirectedGraphNode cloneGraph1(UndirectedGraphNode node) {
     2         if (node == null) {
     3             return null;
     4         }        
     5         
     6         return rec(node, new HashMap<UndirectedGraphNode, UndirectedGraphNode>());
     7     }
     8     
     9     // SOLUTION 1:
    10     // Try to return a copied cloneGraph.
    11     public UndirectedGraphNode rec(UndirectedGraphNode node, HashMap<UndirectedGraphNode, UndirectedGraphNode> map) {
    12         // The base case:
    13         if (map.containsKey(node)) {
    14             // If the map has been copied, just return the node.
    15             return map.get(node);
    16         }
    17         
    18         // create a new node.
    19         UndirectedGraphNode nodeCopy = new UndirectedGraphNode(node.label);
    20         // BUG 2: should put it into the map first. Because we don't want to copy the same node again in the recursion.
    21         
    22         map.put(node, nodeCopy);
    23         for (int i = 0; i < node.neighbors.size(); i++) {
    24             // BUG 1: forget a parameter.
    25             // copy all the children node.
    26             nodeCopy.neighbors.add(rec(node.neighbors.get(i), map));
    27         }
    28         
    29         
    30         
    31         return nodeCopy;
    32     }
    View Code

    Ref: http://m.blog.csdn.net/blog/hellobinfeng/17497883

    Code:

    CloneGraph.java

  • 相关阅读:
    Mobox企业网盘回收站文件清空与恢复的管控
    NAS设备部署后采用Mobox企业云盘来提升管理功能
    企业网盘支持对象存储帮助用户推行私有云
    阿里云登录界面无法输入账号及密码的解决方法
    团队协作管理-任务追踪管理
    windows10 家庭版 无法远程2012的解决
    bat删除多少天前的文件包含子目录
    企业网盘居然支持高速局域网文件传输工具(速度可达20M)
    防范永恒之蓝勒索病毒-XP、Win10文件共享怎样设置
    【OpenGL】学习笔记#2
  • 原文地址:https://www.cnblogs.com/yuzhangcmu/p/4044271.html
Copyright © 2011-2022 走看看