【LEETCODE OJ】Clone Graph

Posted on 2014-04-07 01:42  卢泽尔  阅读(266)  评论(0编辑  收藏  举报

Problem link:

http://oj.leetcode.com/problems/clone-graph/

This problem is very similar to "Copy List with Random Pointer", we need a hash map to map a node and its clone.

The algorithm is 2-pass procedure as follows. 

CLONE-GRAPH(GraphNode node):
  Let MAP be a hash map with pairs of (key=GraphNode, value=GraphNode)
  Let Q be an empty queue
  if node == NULL
    return NULL
  // BFS the graph
  Q.push(node)
  while Q is not empty
    n = Q.pop()
    Duplicate n as m
    MAP[n] = m
    for each nn in n's neighbor
        if not MAP.haskey(nn)
            Q.push(nn)
  // Set the neigbors of clone nodes
  for each key n in MAP
    m = MAP[n]
    for each nn in n's neighbor
        mm = MAP[nn]
        add mm into m's neighbors
  // return the clone of node
  return MAP[node]

However, I implemented the algorithm in python but got LTE in oj.leetcode. Then, I implemented it in C++ and accepted successfully.

The C++ code is as follows.

/**
 * Definition for undirected graph.
 * struct UndirectedGraphNode {
 *     int label;
 *     vector<UndirectedGraphNode *> neighbors;
 *     UndirectedGraphNode(int x) : label(x) {};
 * };
 */
#include <map>
#include <queue>

using namespace std;

class Solution {
public:
    UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
        // Special case:
        if (node == NULL) return NULL;
        
        // Declarations
        map<UndirectedGraphNode*, UndirectedGraphNode*> M;
        queue<UndirectedGraphNode*> Q;
        UndirectedGraphNode* n = NULL;
        
        // BFS from the given node
        Q.push(node);
        while (! Q.empty()) {
            // Pop a node in the queue a n
            n = Q.front(); Q.pop();
            // Clone and map n
            M[n] = new UndirectedGraphNode(n->label);
            // Check n's neighbors
            for(vector<UndirectedGraphNode*>::iterator iter=n->neighbors.begin(); iter != n->neighbors.end(); ++iter) {
                if (M.find(*iter) == M.end()) { // Not found, means not visited yet
                    Q.push(*iter);
                }
            }
        }
        
        // Set neighbors of new created nodes
        for(map<UndirectedGraphNode*, UndirectedGraphNode*>::iterator iter = M.begin(); iter != M.end(); ++iter) {
            // iter->first: the pointer to the original node
            // iter->second: the pointer to the clone
            for(vector<UndirectedGraphNode*>::iterator ni = iter->first->neighbors.begin(); ni != iter->first->neighbors.end(); ++ni)
                iter->second->neighbors.push_back(M[*ni]);
        }
        return M[node];
    }
};

FYI, I also post my python version here even it is not accepted due to LTE# Definition for a undirected graph node

 

# Definition for a undirected graph node
# class UndirectedGraphNode:
#     def __init__(self, x):
#         self.label = x
#         self.neighbors = []

class Solution:
    # @param node, a undirected graph node
    # @return a undirected graph node
    def cloneGraph(self, node):
        """
        Similar to the previous problem "Copy List with Random Pointer"
        which deepcopies a list node containing (value, next, random).
        So we can use similar technique.
        We need to assume that each node has a path to the given node
        """
        # Special case:
        if node is None:
            return None
        
        # We use a dictionary to map between the original node and its copy
        # Also, we can use mapping.keys() to keep track the nodes we already visited
        mapping = {}
        
        # BFS from the given node
        q = [node]
        while q:
            # I do not pop/push on q, since it is not efficient for python build-in list structure
            # Instead, I just create a new empty list, and iterate all elements in q.
            # After adding all neighbors to new_q, set q = new_q
            new_q = []
            for n in q:
                # Clone n and map it with its clone
                mapping[n] = UndirectedGraphNode(n.label)
                # Check its neighbors
                for x in n.neighbors:
                    if x not in mapping.keys():
                        new_q.append(x)
            q = new_q
        
        # All nodes are mapping.keys()
        for n in mapping.keys():
            for x in n.neighbors:
                mapping[n].neighbors.append(mapping[x])
        
        # Return the clone of node
        return mapping[node]