思路:(无向图的复制)
题目要求的是让我们实现一个图的深拷贝。深拷贝指的是复制另外一个对象到自己的对象中,且两者不共享一个内存区,浅拷贝是指两者共享一个内存区
所以我们需要new 来开辟新的内存区执行拷贝。还要注意一个问题。我们这个图实际上是个有向图,如果A有一个相邻顶点B,则A->B, 但是B能否到A取决
于B是否有相邻顶点A. 也就是说如果B能达到A,说明图中存在环,如果不考虑环的存在,我们在拷贝中可能形成死循环。
假设我们从图的A点出发,进行拷贝得到A(A2), 发现A有一个相邻顶点B,然后进行拷贝得到B(B2),然后链接A2->B2,使得B2成为A2的相邻顶点。接着,我
们操作B, 发现B有一个相邻顶点A, 而A我们是已经进行过拷贝的了。如果我们又对A再次进行拷贝, 将形成个死循环,我们要做的仅是将B2->A2连接起来。
如何才能避免这种再次拷贝呢?我们只需要一个map即可,每次我们做一份拷贝,就放入map中,下次查询,如果是已经有的copy就不再继续拷贝,只是连接。
如果没有,就做拷贝,然后连接,然后放入map. map的key是原来的顶点,value是原来定点的copy版。
注:深拷贝是指源对象与拷贝对象相互独立,其中任何一个对象的改动都不会对另一个对象造成影响
/**
* Definition for undirected graph.
* struct UndirectedGraphNode {
* int label;
* vector<UndirectedGraphNode *> neighbors;
* UndirectedGraphNode(int x) : label(x) {};
* };
*/
class Solution {
public:
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
/*BFS 复杂度:O(N),因为我们把每个结点都访问一遍,空间复杂度是栈或者队列加上map的大小,不会超过O(N)。*/
if (node == NULL)
return NULL;
//开辟新的空间存储copy
UndirectedGraphNode *copy = new UndirectedGraphNode(node->label);
//查找去重用的map unordered_map<node, clonedNode> 放原始node和其复制品
unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> cmap;
//存储的队列,进行BFS
queue<UndirectedGraphNode*> graphQ;
graphQ.push(node); //根节点入队列
cmap.insert({node, copy}); //把根节点和其复制品放入map
while (!graphQ.empty())
{
UndirectedGraphNode *cur = graphQ.front(); //处理当前对象
graphQ.pop();
UndirectedGraphNode *curClone = cmap[cur]; //处理对象的复制品,因为前面的neighbor里已经被创建
//对当前顶点的每一个neighbor进行判断,因为有的neighbor已经被复制,有的没有
for (int i = 0; i < cur->neighbors.size(); i++)
{
UndirectedGraphNode *neighbor = cur->neighbors[i];
//如果之前没有拷贝过
if (cmap.find(neighbor) == cmap.end())
{
UndirectedGraphNode *neighborClone = new UndirectedGraphNode(neighbor->label);
curClone->neighbors.push_back(neighborClone); //给curClone添加复制的neighbor
cmap.insert({neighbor, neighborClone}); //添加到map中
graphQ.push(neighbor); //添加到队列为了将来的遍历
}
else //之前已经复制过的neighbor
{
UndirectedGraphNode *neighborClone = cmap[neighbor]; //从map中取出之前的copy版本
curClone->neighbors.push_back(neighborClone); //给curClone添加复制的neighbor
}
}
}
return copy;
}
};