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]