zoukankan      html  css  js  c++  java
  • 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
             / 
             \_/

    这题目的是clone 图,那么遍历原图建立新图的过程不可避免,用BFS或者DFS都可以。但是一点是如何建立将原图之间的结点链接映射到新图当中,old_node,new_node这样的键值对不可避免,需要用到一个hashmap,另外无论DFS还是BFS都需要判断当前的点有没有重复遍历,所以hashmap一箭双雕,

    即一个查原图点有没有遍历过,另外对已经遍历的点,建立旧点和新点的映射。值得注意的是,这题给出的图的定义比较坑,即临接边只会出现在其中一个顶点的临接表中,另外一个不会出现。所以处理当前点的邻居时,不管该邻居之前有没有被遍历过,链接都需要建立。

    BFS代码如下:

    class Solution(object):
        def cloneGraph(self, node):
            """
            :type node: UndirectedGraphNode
            :rtype: UndirectedGraphNode
            """
            if not node:
                return None
            map = {}
            queue = collections.deque()
            queue.append(node)
            newNode = UndirectedGraphNode(node.label)
            map[node] = newNode
            while queue:
                oldNode = queue.popleft()
                for neighbor in oldNode.neighbors:
                    if neighbor not in map:
                        newNode = UndirectedGraphNode(neighbor.label)
                        map[neighbor] = newNode
                        queue.append(neighbor)
                    map[oldNode].neighbors.append(map[neighbor])
                        
            return map[node]

    DFS非递归遍历如下:

    class Solution(object):
        def cloneGraph(self, node):
            """
            :type node: UndirectedGraphNode
            :rtype: UndirectedGraphNode
            """
            if not node:
                return None
            map = {}
            stack = [node]
            map[node.label] = UndirectedGraphNode(node.label)
            while stack:
                cur = stack.pop()
                for neighbor in cur.neighbors:
                    if neighbor.label not in map:
                        map[neighbor.label] = UndirectedGraphNode(neighbor.label)
                        stack.append(neighbor)
                    map[cur.label].neighbors.append(map[neighbor.label])
            return map[node.label]

    DFS递归遍历:

    class Solution(object):
        def cloneGraph(self, node):
            """
            :type node: UndirectedGraphNode
            :rtype: UndirectedGraphNode
            """
            if not node:
                return None
            map = {}
            map[node] = UndirectedGraphNode(node.label) 
            self.dfs(node, map)
            return map[node]
        def dfs(self, node, map):
            for neighbor in node.neighbors:
                if neighbor not in map:
                    map[neighbor] = UndirectedGraphNode(neighbor.label)
                    self.dfs(neighbor, map)
                map[node].neighbors.append(map[neighbor])

    这三种做法的时间复杂度都是O(V+E),结点入栈或者队列一次,出一次,边也要扫一次,判断。注意这题结点的值都不一样,为了节省空间,可以只使用原结点的值做hashmap的键值。

  • 相关阅读:
    switch_goto
    隐藏 窗口的整个 标题栏(包括右上角的关闭)
    asp的邦定表达式异常 <_ %_ = strParentid _%_>不能传到下个页面
    【收藏】default.rdp配置
    计算机网络中的性能指标
    当某个快捷键不能用时很可能是热键冲突
    java的FOR循环 打印三角形
    二进制 八进制 十进制 十六进制
    linux的vim编辑命令常用
    JIRA的备份
  • 原文地址:https://www.cnblogs.com/sherylwang/p/5596797.html
Copyright © 2011-2022 走看看