题目:
Clone an undirected graph. Each node in the graph contains a label
and a list
of its neighbors
.
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 as
0
. Connect node0
to both nodes1
and2
. - Second node is labeled as
1
. Connect node1
to node2
. - Third node is labeled as
2
. Connect node2
to node2
(itself), thus forming a self-cycle.
Visually, the graph looks like the following:
1 / \ / \ 0 --- 2 / \ \_/
给一个图,将这个图复制给另一个图,其中图描述是这样的,如果有节点重复,那么就不考虑了,正如上面题目中写的那样,比如上面的那个图,就是这样复制的,那么我们在复制的时候,考虑用DFS或者是BFS来做,当然在实际操作的时候,用map来存储相关的节点信息,用map来排除已经复制过的节点信息。其实复制过程采用两个遍历来做,首先是用一个map来保存图中的所有节点,其中key和value分别表示的是旧的图每个节点和新的图每个节点,那么首先如果用DFS来做,那么就是用栈来做;如果换成是BFS,那么就是采用队列来保存。每一次外循环的时候,我们保存的是图中的所有的节点,而内层循环保存的是新的节点的邻居节点。但是如果碰到有环的情况,那么我们就可以将这个节点直接加到刚才的那个节点中去。
public class Solution
{
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node)
{
if(node == null)
return null;
Stack<UndirectedGraphNode> stack = new Stack<UndirectedGraphNode>();
HashMap<UndirectedGraphNode,UndirectedGraphNode> map = new HashMap<UndirectedGraphNode,UndirectedGraphNode>();
UndirectedGraphNode newHead = new UndirectedGraphNode(node.label);
stack.push(node);
map.put(node, newHead);
while(!stack.isEmpty())
{
UndirectedGraphNode curr = stack.pop();
List<UndirectedGraphNode> currneighbors = curr.neighbors;
for(UndirectedGraphNode aneighbor : currneighbors)
{
if(!map.containsKey(aneighbor))
{
UndirectedGraphNode copy = new UndirectedGraphNode(aneighbor.label);
map.put(aneighbor, copy);
map.get(curr).neighbors.add(copy);
stack.add(aneighbor);
}
else
{
map.get(curr).neighbors.add(map.get(aneighbor));
}
}
}
return newHead;
}
}
以上是用栈来做的,也就是DFS;再来一种用队列来做的,就是BFS。
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node)
{
if(node == null)
return null;
LinkedList<UndirectedGraphNode> queue = new LinkedList<UndirectedGraphNode>();
HashMap<UndirectedGraphNode,UndirectedGraphNode> map = new HashMap<UndirectedGraphNode,UndirectedGraphNode>();
UndirectedGraphNode newHead = new UndirectedGraphNode(node.label);
queue.add(node);
map.put(node, newHead);
while(!queue.isEmpty())
{
UndirectedGraphNode current = queue.pop();
List<UndirectedGraphNode> currNeighbors = current.neighbors;
for(UndirectedGraphNode aNeighbor : currNeighbors)
{
if(!map.containsKey(aNeighbor))
{
UndirectedGraphNode copy = new UndirectedGraphNode(aNeighbor.label);
map.put(aNeighbor, copy);
map.get(current).neighbors.add(copy);
queue.add(aNeighbor);
}
else
{
map.get(current).neighbors.add(map.get(aNeighbor));
}
}
}
return newHead;
}
这两种方法都是异曲同工的,而且我们可以看到原理基本都是一致的,所以我们在做的时候,每次都是把节点加进来。