摘要:开始看这道题目的时候,没有看懂和的作用。然后对这个放入的结点开始操作遍历的所有,当前遍历到的的叫做。当完成,则中没有新的结点了,退出循环。返回在中更新过的,结束。
Problem
Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors.
We use # as a separator for each node, and , as a separator for node label and each neighbor of the node.
return a deep copied graph.
ExampleHow we serialize an undirected graph.
Nodes are labeled uniquely.
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 as 0. Connect node 0 to both nodes 1 and 2.
Second node is labeled as 1. Connect node 1 to node 2.
Third node is labeled as 2. Connect node 2 to node 2 (itself), thus forming a self-cycle.
Visually, the graph looks like the following:
1
/
/
0 --- 2
/
\_/
Note
开始看这道题目的时候,没有看懂queue和hashmap的作用。
复制一个无向图,先分析图的结构:label相当于图结点的value,而neighbors相当于图结点的所有next。然后考虑用什么方式复制:用queue用来标记当前正在复制的或已经复制过的结点cur,而hashmap用来进行对新建无向图结点root进行复制label和neighbors的操作。首先,从node结点开始,放入queue。然后对这个放入queue的结点cur开始操作:遍历cur的所有neighbors,当前遍历到的的neighbors叫做next。若map中不存在这个点,即没有被复制过,就在map中复制这个结点next的label,同时存入queue以便在下次循环取出并复制其neighbors;无论map中包不包含这个neighbors结点next,都要将next加入map中对应新建结点root的neighbors。当BFS完成,则queue中没有新的结点了,退出while循环。返回在map中更新过的root,结束。
map.get(cur).neighbors.add(map.get(next));
这一句可以理解为,在for循环对cur的neighbors的遍历中,先在HashMap里的root中建立新结点next,再将next放进root的结点cur的neighbors里。
// Definition for undirected graph.
class UndirectedGraphNode {
int label;ArrayList neighbors;
UndirectedGraphNode(int x) {
label = x;
neighbors = new ArrayList();
}
}
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) return null;
UndirectedGraphNode root = new UndirectedGraphNode(node.label);//复制根节点
Queue queue = new LinkedList<>();
Map map = new HashMap<>();
queue.offer(node);//queue放入根结点
map.put(node, root);//map放入根结点和它的复制结点
while (!queue.isEmpty()) {
UndirectedGraphNode cur = queue.poll();//取出queue中(同一层)的结点进行BFS
for (UndirectedGraphNode n: cur.neighbors) {
//对没有复制过的结点进行复制,并将这个结点放入queue
if (!map.containsKey(n)) {
map.put(n, new UndirectedGraphNode(n.label));
queue.offer(n);
}
//连接复制结点和复制neighbor结点
map.get(cur).neighbors.add(map.get(n));
}
}
return root;
}
}
Update 2018-9 BFS
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if (node == null) return node;
Map map = new HashMap<>();
map.put(node, new UndirectedGraphNode(node.label)); //: <原结点, 复制结点>
Queue queue = new LinkedList<>();
queue.offer(node); //copy过的结点存入queue,以继续遍历其neighbor结点
while (!queue.isEmpty()) {
UndirectedGraphNode cur = queue.poll(); //取出copy过的结点,继续复制其所有neighbor结点
for (UndirectedGraphNode neighbor: cur.neighbors) {
if (!map.containsKey(neighbor)) { //若结点未复制过,copy后存入queue
map.put(neighbor, new UndirectedGraphNode(neighbor.label));
queue.offer(neighbor);
}
map.get(cur).neighbors.add(map.get(neighbor)); //将每个copied neighbor存入copied parent node
}
}
return map.get(node); //返回copied根节点
}
}
DFS
public class Solution {
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
Map map = new HashMap<>();
return cloneNode(node, map);
}
private UndirectedGraphNode cloneNode(UndirectedGraphNode node, Map map) {
if (node == null) return node;
if (map.containsKey(node)) {
return map.get(node);
} else {
UndirectedGraphNode nodeCopy = new UndirectedGraphNode(node.label);
map.put(node, nodeCopy);
for (UndirectedGraphNode child : node.neighbors) {
nodeCopy.neighbors.add(cloneNode(child, map));
}
return nodeCopy;
}
}
}
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/65729.html
摘要:解题思路涉及到图的遍历无非就是深度优先搜索广度优先搜索,可以先看前几日的这篇文章就需要借助队列实现,可以借助栈也可以直接用递归实现。 题目: 给定无向连通图中一个节点的引用,返回该图的深拷贝(克隆)。图中的每个节点都包含它的值 val(Int) 和其邻居的列表(list[Node])。 Given a reference of a node in a connected undirec...
1. 说明 本文所有的算法严格按照《算法导论》,本文将详细的对BFS和DFS进行分析,并提供算法的 js 实现,同时会对创建链表的方式进行优化 2. 图的表示 图的表示分为对顶点集 V 的表示和对边集 E 的表示,这里的重点是如何表示边,边的表示分为邻接矩阵和邻接链表这两种表示方法,邻接矩阵适合表示边稠密的图,其消耗空间为|V|*|V|,如果是无向图,则可以用上三角矩阵或者下三角矩阵来表示,是空间...
摘要:但是一个偏序关系,如果我们默认,先出现的排在前面,那么我们就能比较,的关系了。对于算法的每个节点,我们都有一个发现时间,一个访问时间,当运行完成时,对于图中的任意一条边,都有所以拓扑排序的次序与顶点的完成时间恰好相反。 1. 偏序和全序的概念 1.1. 偏序 设R是集合A上的一个二元关系,若R满足下列三个性质则称R为A上的偏序关系自反性:对任意x∈A,有∈R反对称性:对任意的x,y∈A...
Problem There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolling up, down, left or right, but it wont stop rolling until hitting a wall. When the ball sto...
摘要:生成树和最小生成树的概念设图连通,则生成树包含图中的所有节点,及条边的连通图,一个图的生成树可以有多颗最小生成树最小权重生成树,在生成树的概念上加一个限制条件,即生成树的所有边的权值总和最小的树,最小生成树也可以有多颗求解最小生成树的通用 1. 生成树和最小生成树的概念 设图G(V,E)连通,则生成树:包含图G(V,E)中的所有节点,及|V|-1条边的连通图,一个图的生成树可以有多颗最...
阅读 2122·2023-04-25 23:28
阅读 881·2023-04-25 22:49
阅读 2813·2021-09-27 13:34
阅读 5674·2021-09-22 15:09
阅读 3791·2019-08-30 12:52
阅读 2945·2019-08-29 15:26
阅读 868·2019-08-29 11:12
阅读 2381·2019-08-26 12:24