要想clone整个图,那么我们肯定要遍历一遍图,遍历图有两种基本的思路:DFS和BFS。即我们可以对某个节点访问时对其实现拷贝。
我们一般在用DFS时都会开辟一个visited数组来记录某个节点是否被访问过,此题也类似, 我们可以用一个map(或者更快的unordered_map)来记录某个节点是否已被拷贝,而且我们可以顺便用这个map记录原节点及其复本的映射关系,即 map存放的是一个节点到节点的映射。
也可以使用 BFS 来遍历图,使用队列 queue 进行辅助,还是需要一个map来建立原图节点与其复本之间的映射。 先拷贝当前结点,然后建立映射,并加入queue中,进行 while 循环。在循环中,取出队首结点,遍历其所有邻居, 若某邻居不在map中,说明这个邻居未被拷贝,则需要进行拷贝并建立映射然后将邻居送入queue中。 遍历完所有邻居后需要将当前节点的所有邻居的复本加入到当前节点的复本的neighbors数组,然后进入下一循环。
class Solution {
private:
Node* DFS_copy(Node* node, unordered_map<Node*, Node*>&mp){
if(!node) return NULL;
if(mp.count(node)) return mp[node]; # 之前已被拷贝
Node* node_cp = new Node(node->val);
mp[node] = node_cp;
for(int i = 0; i < (node->neighbors).size(); i++){
node_cp -> neighbors.push_back(DFS_copy((node->neighbors)[i], mp));
}
return node_cp;
}
public:
Node* cloneGraph(Node* node) {
unordered_map<Node*, Node*>mp;
return DFS_copy(node, mp);
}
};
class Solution {
public:
Node* cloneGraph(Node* node) {
if (!node) return NULL;
unordered_map<Node*, Node*> m;
queue<Node*> q;
q.push(node);
Node *node_cp = new Node(node->val);
m[node] = node_cp;
while (!q.empty()) {
Node *t = q.front(); q.pop();
for (Node *nb : t->neighbors) { // 注意这种写法
if (!m.count(nb)) { // 如果没被拷贝
m[nb] = new Node(nb->val); //先访问再入队
q.push(nb);
}
// 此时所有邻居确保已被拷贝过
m[t]->neighbors.push_back(m[nb]);
}
}
return node_cp;
}
};