1.题目
克隆一张无向图,图中的每个节点包含一个 label
和一个列表 neighbors
。
数据中如何表示一个无向图?http://www.lintcode.com/help/graph/
你的程序需要返回一个经过深度拷贝的新图。这个新图和原图具有同样的结构,并且对新图的任何改动不会对原图造成任何影响。
比如,序列化图 {0,1,2#1,2#2,2}
共有三个节点, 因此包含两个个分隔符#。
- 第一个节点label为0,存在边从节点0链接到节点1和节点2
- 第二个节点label为1,存在边从节点1连接到节点2
- 第三个节点label为2,存在边从节点2连接到节点2(本身),从而形成自环。
我们能看到如下的图:
1
/ \
/ \
0 --- 2
/ \
\_/
2.算法
图的遍历分为广度优先搜索和深度优先搜索,我们主要从这两个方面解这个题
算法1:广度优先搜索。广度优先搜索是用队列存储每一排的数据,可以用旧结点和新结点的HashMap来做visited的记录
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node)
{
// write your code here
if (node == null)
{
return null;
}
LinkedList<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>();
HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>();
UndirectedGraphNode copy = new UndirectedGraphNode(node.label);
queue.offer(node);
map.put(node, copy);
while (!queue.isEmpty())
{
UndirectedGraphNode cur = queue.poll();
for (int i = 0; i < cur.neighbors.size(); i++)
{
if (!map.containsKey(cur.neighbors.get(i)))
{
copy = new UndirectedGraphNode(cur.neighbors.get(i).label);
map.put(cur.neighbors.get(i), copy);
queue.offer(cur.neighbors.get(i));
}
map.get(cur).neighbors.add(map.get(cur.neighbors.get(i)));
}
}
return map.get(node);
}
步骤主要是,1先把头结点放在队列中,并拷贝节点到hashmap中。
2.如果对列中有元素,出队列node,并把node所关联的节点复制到hashmap中(如果有则不用复制),并把他加到队列中,最后让新节点关联起来
算法2:深度优先搜索,栈的顺序是后进先出,所以用栈来做,下次循环pop出来是刚刚插入的结点,所以是把子节点先搜索之后再回到原先结点的邻居
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node)
{
// write your code here
if (node == null)
{
return null;
}
LinkedList<UndirectedGraphNode> stack = new LinkedList<UndirectedGraphNode>();
HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>();
UndirectedGraphNode copy = new UndirectedGraphNode(node.label);
stack.push(node);
map.put(node, copy);
while (!stack.isEmpty())
{
UndirectedGraphNode cur = stack.pop();
for (int i = 0; i < cur.neighbors.size(); i++)
{
if (!map.containsKey(cur.neighbors.get(i)))
{
copy = new UndirectedGraphNode(cur.neighbors.get(i).label);
map.put(cur.neighbors.get(i), copy);
stack.push(cur.neighbors.get(i));
}
map.get(cur).neighbors.add(map.get(cur.neighbors.get(i)));
}
}
return map.get(node);
}
其中深度优先遍历可以用递归来实现
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node)
{
// write your code here
if (node == null)
{
return null;
}
HashMap<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<UndirectedGraphNode, UndirectedGraphNode>();
UndirectedGraphNode copy = new UndirectedGraphNode(node.label);
map.put(node, copy);
helper(node, map);
return map.get(node);
}
public void helper(UndirectedGraphNode node, HashMap<UndirectedGraphNode, UndirectedGraphNode> map)
{
for (int i = 0; i < node.neighbors.size(); i++)
{
UndirectedGraphNode cur = node.neighbors.get(i);
if (!map.containsKey(cur))
{
UndirectedGraphNode copy = new UndirectedGraphNode(cur.label);
map.put(cur, copy);
helper(cur, map);
}
map.get(node).neighbors.add(map.get(cur));
}
}