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的键值。

 

posted on 2016-06-18 20:21  Sheryl Wang  阅读(181)  评论(0编辑  收藏  举报

导航