Leetcode:133.克隆图
克隆一张无向图,图中的每个节点包含一个 label
(标签)和一个 neighbors
(邻接点)列表 。
OJ的无向图序列化:
节点被唯一标记。
我们用 #
作为每个节点的分隔符,用 ,
作为节点标签和邻接点的分隔符。
例如,序列化无向图 {0,1,2#1,2#2,2}
。
该图总共有三个节点, 被两个分隔符 #
分为三部分。
- 第一个节点的标签为
0
,存在从节点0
到节点1
和节点2
的两条边。 - 第二个节点的标签为
1
,存在从节点1
到节点2
的一条边。 - 第三个节点的标签为
2
,存在从节点2
到节点2
(本身) 的一条边,从而形成自环。
我们将图形可视化如下:
1 / \ / \ 0 --- 2 / \ \_/
解题思路:
广度优先搜索,映射(unordered_map)。图的克隆,也就是建立一个新的图,使得旧图和新图的结构一致,每个结点存在映射关系,并且对应结点的值相等,并且邻居的值也对应相等。
- 建立映射关系,结点与结点的映射。unordered_map<UndirectedGraphNode*, UndirectedGraphNode*>mp;
- 设置广度搜索需要的队列,Q,Qc分别对应原图队列以及克隆图队列。
- 首先克隆图的第一个结点,*clone=new UndirectedGraphNode(node->label)。建立这两个结点的映射关系mp[node]=clone。
- 下一步将克隆node结点的邻居。克隆邻居时会遇到两种情况原图的邻居不能映射到新图,也就意味着,需要创建新的结点然后建立映射关系。或者能找到映射关系,说明这对结点之前访问过。例如,上面访问上图的1时,邻居0能找到映射,因为之前被访问,而邻居2结点不能找到映射。不论之间有没有访问都需要将邻居加入。
- 加入邻居之后,如果这个结点刚刚才被创建,那么将这对结点分别加入自己的队列。之后将当前访问的结点出队。
- 直到队列为空,说明图克隆完毕,return clone。
class Solution { public: UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) { if (node == NULL) return NULL; queue<UndirectedGraphNode*> Q,Qc; UndirectedGraphNode *clone=new UndirectedGraphNode(node->label), *temp,*tempc; unordered_map<UndirectedGraphNode*, UndirectedGraphNode*>mp;//两个图的映射 Q.push(node); Qc.push(clone); mp[node] = clone; UndirectedGraphNode *p; while (!Q.empty()) { temp = Q.front(); tempc = Qc.front(); int size = temp->neighbors.size(); for (int i = 1; i <= size; i++) { p = temp->neighbors[i - 1]; if (mp[p] == NULL) { UndirectedGraphNode* newC = new UndirectedGraphNode(p->label); tempc->neighbors.push_back(newC); Q.push(p); Qc.push(newC); mp[p] = newC; } else { tempc->neighbors.push_back(mp[p]); } } Q.pop(); Qc.pop(); } return clone; } }; |