leetcode之clone-graph复制图
题目
Clone an undirected graph. Each node in the graph contains alabeland a list of itsneighbors.
OJ’s undirected graph serialization:
Nodes are labeled uniquely.
We use#as a separator for each node, and,as a separator for node label and each neighbor of the node.
As an example, consider the serialized graph{0,1,2# 1,2# 2,2}.
The graph has a total of three nodes, and therefore contains three parts as separated by#.
First node is labeled as0. Connect node0to both nodes1and2.
Second node is labeled as1. Connect node1to node2.
Third node is labeled as2. Connect node2to node2(itself), thus forming a self-cycle.
Visually, the graph looks like the following:
题意
拷贝一个无向图,图中的每一个节点都包含一个label数值和一个邻居节点列表;
其中节点的label是唯一的;
解题思路
这道题目考察的图的遍历,这里我们使用BFS来进行解题,但是跟传统的BFS不一样的是,我们需要一个map,来维护这个邻居节点是否是已经被之前遍历过,如果之前被遍历过,那么就不需要再去copy一份了,但是邻居关系还是需要重新建立的。
或者我们直接使用DFS的递归来进行处理,则只需要在递归dfs复制新节点的时候,直接去维护邻居表,邻居表里再去递归copy新节点,如果新节点在这个map里面已经有了,则直接返回新节点,同时维护邻居关系。
Java源码
链接:https://www.nowcoder.com/questionTerminal/5ec76def9d7b420794091727a97f0dc6
来源:牛客网
/**
* 题目解析:给定一个无向图,图内节点包括节点值、节点的邻居;需要复制该图
* 解题思路:
* 图的遍历可添加一个辅助队列来左广度优先搜索
* 再者,因为节点未给是否已经访问的属性,可以添加一个map来记录已经访问的节点,和复制的节点
* 同时map帮助复制 邻居节点
*/
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) {
return null;
}
// 建立辅助队列
LinkedList<UndirectedGraphNode> queue = new LinkedList<>();
// 建立map,跟踪已经访问的节点
Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>();
// 节点入队
queue.offer(node);
// 复制节点-只复制了label域,neighbors域是引用对象,直接复制无意义
UndirectedGraphNode newNode = new UndirectedGraphNode(node.label);
// 节点进入代表已经访问的map
map.put(node, newNode);
// 中断条件:队列为空
while(!queue.isEmpty()) {
// 出队
UndirectedGraphNode temp = queue.poll();
// 获取邻居,遍历邻居
ArrayList<UndirectedGraphNode> neighbors = temp.neighbors;
for(UndirectedGraphNode neighbor : neighbors) {
// 声明当前邻居节点 的 复制节点
UndirectedGraphNode copy;
// 若邻居未访问过
if (!map.containsKey(neighbor)) {
// 该邻居节点入队
queue.offer(neighbor);
// 复制该邻居节点
copy = new UndirectedGraphNode(neighbor.label);
// 将未访问邻居记录进map
map.put(neighbor, copy);
} else {
// 邻居节点 之前被访问过
// 获取邻居节点的复制节点
copy = map.get(neighbor);
}
// 无论当前邻居节点 是否被访问过
// 它的复制节点 都应该跟 复制的根节点建立 邻居关系
map.get(temp).neighbors.add(copy);
}
}
// 返回 复制的图
return newNode;
}
C++源码
/**
* Definition for undirected graph.
* struct UndirectedGraphNode {
* int label;
* vector<UndirectedGraphNode *> neighbors;
* UndirectedGraphNode(int x) : label(x) {};
* };
*/
class Solution {
public:
map<UndirectedGraphNode*,UndirectedGraphNode*> mp;
UndirectedGraphNode *dfs(UndirectedGraphNode *node) {
if(mp.count(node)){
return mp[node];
}
UndirectedGraphNode* newNode = new UndirectedGraphNode(node->label);
mp[node]=newNode;
//遍历原节点的邻居列表,返回所有邻居列表的节点的copy节点
for(int i=0;i<node->neighbors.size();i++){
newNode->neighbors.push_back(dfs(node->neighbors[i]));
}
return newNode;
}
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
if(node == nullptr)
return nullptr;
return dfs(node);
}
};