题目来源
题目描述
class Node {
public:
int val;
vector<Node*> neighbors;
Node() {
val = 0;
neighbors = vector<Node*>();
}
Node(int _val) {
val = _val;
neighbors = vector<Node*>();
}
Node(int _val, vector<Node*> _neighbors) {
val = _val;
neighbors = _neighbors;
}
};
class Solution {
public:
Node* cloneGraph(Node* node) {
}
};
题目解析
这道题本质是要求遍历一个图,通常有两种方法
深度优先遍历
为了深拷贝出整张图,我们需要知道整张图的结构已经对应节点的值。
由于题目值给了我们一个节点的引用,因此为了知道整张图的结构已经对应节点的值,我们需要从给定的节点出发,进行图的遍历,并在遍历的过程中完成图的深拷贝
为了避免在深拷贝时陷入死循环,我们需要理解图的结构。对于一张无向图,任何给定的无向边都可以表示为两个有向边
为了防止多次遍历同一个节点,陷入死循环,我们需要一种数据结构记录已经被克隆过的节点
算法:
- 使用一个哈希表存储所有已经被访问和克隆的节点。key是原始图中的节点,value是克隆对应节点
- 从给定节点开始遍历图。如果某个节点已经被访问过,则返回其克隆图中的对应节点。
- 如果当前访问的节点不在哈希表中,则创建它的克隆节点并存储在哈希表中。
- 递归调用克隆每个节点的邻接点。
class Solution {
std::unordered_map<Node*, Node *> visited;
public:
Node* cloneGraph(Node* node) {
if(node == nullptr){
return nullptr;
}
if(visited[node] != nullptr){
return visited[node];
}
Node* clone = new Node(node->val);
visited[node] = clone;
for(auto & neighbor : node->neighbors){
clone->neighbors.emplace_back(cloneGraph(neighbor));
}
return clone;
}
};
广度优先遍历
方法一与方法二的区别仅在于搜索的方式。深度优先搜索以深度优先,广度优先搜索以广度优先。这两种方法都需要借助哈希表记录被克隆过的节点来避免陷入死循环。
算法
- 使用一个哈希表visited存储所有已经被访问和克隆的节点。哈希表中的key是原始图中的节点,value是克隆图中的节点
- 将题目中给定的节点添加到队列。克隆该节点并存储到哈希表
- 每次从队列首部取出一个节点,遍历该节点所有的邻接点。
- 如果某个邻接点已经被访问,则该邻接点一定在visited中,那么从从 visited 获得该邻接点,否则创建一个新的节点存储在 visited 中,并将邻接点添加到队列。将克隆的邻接点添加到克隆图对应节点的邻接表中。
- 重复上述操作直到队列为空,则整个图遍历结束。
class Solution {
public:
Node* cloneGraph(Node* node) {
if(node == nullptr){
return nullptr;
}
std::unordered_map<Node*, Node *> visited;
std::queue<Node *> queue;
queue.push(node);
visited[node] = new Node(node->val);
while (!queue.empty()){
auto orignal_node = queue.front(); queue.pop();
auto clone_node = visited[orignal_node];
for(auto neighbor : orignal_node->neighbors){
auto cloneNeighbor = visited[neighbor];
if(cloneNeighbor == nullptr){
cloneNeighbor = new Node(neighbor->val);
visited[neighbor] = cloneNeighbor;
queue.push(neighbor);
}
clone_node->neighbors.emplace_back(cloneNeighbor);
}
}
return visited[node];
}
};
类似题目
题目 | 思路 |
---|---|
leetcode:133. 克隆图 Clone Graph | |
leetcode:138. 复制带随机指针的链表 Copy List with Random Pointer |