zoukankan      html  css  js  c++  java
  • 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的子类,计算完成后,将结果强转为父类。

  • 相关阅读:
    LVS基于DR模式负载均衡的配置
    Linux源码安装mysql 5.6.12 (cmake编译)
    HOSt ip is not allowed to connect to this MySql server
    zoj 3229 Shoot the Bullet(无源汇上下界最大流)
    hdu 3987 Harry Potter and the Forbidden Forest 求割边最少的最小割
    poj 2391 Ombrophobic Bovines(最大流+floyd+二分)
    URAL 1430 Crime and Punishment
    hdu 2048 神、上帝以及老天爷(错排)
    hdu 3367 Pseudoforest(最大生成树)
    FOJ 1683 纪念SlingShot(矩阵快速幂)
  • 原文地址:https://www.cnblogs.com/yanyichao/p/3944814.html
Copyright © 2011-2022 走看看