This problem is designed to test your ability to traverse a graph.
There are two systematic ways to do so: Bread-First Search (BFS) and Depth-First Search (DFS).
BFS requires using a queue to store the nodes to be visited while DFS may give a succinct recursive solution. For details about BFS and DFS, you may refer to Introduction to Algorithms. In the following parts, I am going to focus on what I think is the most tricky part in this problem, that is, what is beyond graph traversal to clone a graph?
In order to clone a graph, you need to have a copy of each node in the original graph. Well, you may not have too many ideas about it. Let's do an example.
Suppose we are given a graph {0, 1 # 1, 0}. We know that the graph has two nodes 0 and 1 and they are connected to each other.
We now start from 0. We make a copy of 0. Then we check 0's neighbors and we see 1. We make a copy of 1 and we add the copy to the neighbors of the copy of 0. Now the cloned graph is {0 (copy), 1 (copy)}. Then we visit 1. We make a copy of 1... well, wait, why do we make another copy of it? We already have one! Note that if you make a new copy of the node, these copies are not the same and the graph structure will be wrong! Now you see the trickiest part of this problem. In fact, we need to maintain a mapping from each node to its copy. If the node has a copy, we simply use the existed copy. So the remaining process is that we visit the copy of 1 and add the copy of 0 to its neighbors and the cloned graph is eventually {0 (copy), 1 (copy) # 1 (copy), 0 (copy)}.
Note that the above process uses BFS. Of course, you can use DFS. The key is the node-copy mapping, anyway.
The following is the BFS code.
1 class Solution { 2 public: 3 UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) { 4 if (!node) return NULL; 5 UndirectedGraphNode* copy = new UndirectedGraphNode(node -> label); 6 mp[node] = copy; 7 queue<UndirectedGraphNode*> toVisit; 8 toVisit.push(node); 9 while (!toVisit.empty()) { 10 UndirectedGraphNode* cur = toVisit.front(); 11 toVisit.pop(); 12 for (int i = 0; i < (int)cur -> neighbors.size(); i++) { 13 UndirectedGraphNode* neigh = cur -> neighbors[i]; 14 if (mp.find(neigh) == mp.end()) { 15 UndirectedGraphNode* neigh_copy = new UndirectedGraphNode(neigh -> label); 16 mp[neigh] = neigh_copy; 17 toVisit.push(neigh); 18 } 19 mp[cur] -> neighbors.push_back(mp[neigh]); 20 } 21 } 22 return copy; 23 } 24 private: 25 unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> mp; 26 };
This one is a very succinct DFS code taken from this link.
1 class Solution { 2 public: 3 UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) { 4 if (!node) return NULL; 5 if (mp.find(node) == mp.end()) { 6 mp[node] = new UndirectedGraphNode(node -> label); 7 for (UndirectedGraphNode* neigh : node -> neighbors) 8 mp[node] -> neighbors.push_back(cloneGraph(neigh)); 9 } 10 return mp[node]; 11 } 12 private: 13 unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> mp; 14 };
If you want to learn more about this problem, you may refer to this passage.