• Clone Graph


    1 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 #.

    1. First node is labeled as 0. Connect node 0 to both nodes 1 and 2.
    2. Second node is labeled as 1. Connect node 1 to node 2.
    3. 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
             / 
             \_/
    

     解析:

    1 先复制节点,再复制节点的neighbors关系。

    2 label是唯一的,可以用label作为Map的key,以确定哪些节点已经复制。

     代码如下:

     1 package leetcode;
     2 
     3 import java.util.ArrayList;
     4 import java.util.HashMap;
     5 import java.util.HashSet;
     6 import java.util.List;
     7 import java.util.Map;
     8 import java.util.Set;
     9 
    10 public class CloneGraph {
    11     class UndirectedGraphNode {
    12         int label;
    13         List<UndirectedGraphNode> neighbors;
    14         Set<UndirectedGraphNode> set = new HashSet<CloneGraph.UndirectedGraphNode>();
    15 
    16         UndirectedGraphNode(int x) {
    17             label = x;
    18             neighbors = new ArrayList<UndirectedGraphNode>();
    19         }
    20 
    21         public String toString(Set<UndirectedGraphNode> set) {
    22             if (set.contains(this)) {
    23                 return "";
    24             }
    25             set.add(this);
    26 
    27             String s = label + ",";
    28             for (UndirectedGraphNode neighbor : neighbors) {
    29                 s += neighbor.label + ",";
    30             }
    31             s += "#";
    32 
    33             for (UndirectedGraphNode neighbor : neighbors) {
    34                 s += neighbor.toString(set);
    35             }
    36             return s;
    37         }
    38 
    39         @Override
    40         public String toString() {
    41             set.clear();
    42             return toString(set);
    43         }
    44     };
    45 
    46     private void cloneNode(UndirectedGraphNode node, Map<Integer, UndirectedGraphNode> map) {
    47 
    48         if (map.containsKey(node.label)) {
    49             return;
    50         }
    51         
    52         UndirectedGraphNode nodeClone = new UndirectedGraphNode(node.label);
    53         map.put(node.label, nodeClone);
    54         for (UndirectedGraphNode neighbor : node.neighbors) {
    55             cloneNode(neighbor, map);
    56         }
    57         return;
    58     }
    59 
    60     private void cloneNeighbors(UndirectedGraphNode node, UndirectedGraphNode nodeClone, Map<Integer, UndirectedGraphNode> map) {
    61         
    62         if (node.neighbors.size() == nodeClone.neighbors.size()) {
    63             return;
    64         }
    65         
    66         for (UndirectedGraphNode neighbor : node.neighbors) {
    67             nodeClone.neighbors.add(map.get(neighbor.label));
    68         }
    69         
    70         for (UndirectedGraphNode neighbor : node.neighbors) {
    71             cloneNeighbors(neighbor, map.get(neighbor.label), map);
    72         }
    73     }
    74 
    75     public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
    76         if (node == null) {
    77             return null;
    78         }
    79 
    80         // 复制节点
    81         Map<Integer, UndirectedGraphNode> map = new HashMap<Integer, UndirectedGraphNode>();
    82         cloneNode(node, map);
    83         
    84         UndirectedGraphNode nodeClone = map.get(node.label);
    85 
    86         // 复制neighbors关系
    87         cloneNeighbors(node, nodeClone, map);
    88         
    89         return nodeClone;
    90     }
    91 }
    View Code

    2 题外话

    本题有坑:

    (1) 无向图,node2是node1的neighbors,不代表node1是node2的neighbors。

    本来是准备将nodeClone挂到node的最后一个neighbors,然后复制nodeClone的neighbors关系,再断开node和nodeClone的连接。

    这样时间复杂度为O(n),空间复杂度O(1)。

    这么做的瓶颈在于最后无法区分哪些是node的节点,哪些是clone的节点。这个需要存在如下假设:有node1.neighbors.contains(node2),则必有node2.neighbors.contains(node1)。

    (2) 本题label唯一不通用,可以取node作为Map的key,这就需要为UndirectedGraphNode添加node的hashCode()和equals()方法,而leetcode是不允许修改这个的。一方面,平时我们是可以修改类的;另一方面,我们可以创建UndirectedGraphNode的子类,计算完成后,将结果强转为父类。

  • 相关阅读:
    建立一个简单的通讯录
    建立一个图书管理系统(oc)
    OC 学习第六天(敲代码时遇到的一些错误)
    Serv-U FTP Server 15.1.2学习笔记
    Myeclipse&Tomcat中遇到的部分问题---其一
    MySQL存储过程和函数(三)
    MySQL存储过程和函数(二)
    MySQL存储过程和函数(一)
    mybatis拦截器分页
    Java--最大子序列和实现
  • 原文地址:https://www.cnblogs.com/yanyichao/p/3944814.html
Copyright © 2020-2023  润新知