这个题其实和Copy List with Random Pointer是一个思路
首先一点是,clone就是要把这个图完整的复制出来,也就是,每个node,和对应的neighbor关系都要复制出来。
其次, 题中说了没有重复的label,那么就说,每个点都是不一样的。然后,每个node都有邻居,所以那么我们在遍历的时候,不能把相同的点复制多个(比如1的邻居是【2,3】, 2的邻居是【1,3】,如果出现了2个【3】,就不对了)
思路是:
对于图的遍历,我们应该想到BFS,那么需要一个栈Queue, 用来一层一层的遍历图。那么如果能把原图和克隆图对应起来,那么就可一边遍历原图,一边创建克隆图。
我们可以看出这是个映射关系,用HashMap肯定是一个不错的选择。所以我们建了一个map,<key-当前图节点,value-克隆图节点>
然后我们做好准备工作:把原图node放入栈中,建一个新的复制节点newNode(作为复制图的初始节点,方便我们操作),把这个关系放在map中。
然后再理下思路:
现在我们有一个栈,栈里存放了最原始的node。那么我们开始循环,每次把栈里的点拿出来,访问它的邻居,把每个相邻节点都加到栈中,依次循环,直到栈不为空。这是BFS的思想。
那么对于这个题来说,既然我们已经有了当前复制节点newNode,那么它和相邻节点的关系就是原图里的关系。 但是我们要克隆,不能拿原图里的点来用。所以每次要新建一个克隆节点。注意:新建克隆节点,我们不需要管它的相邻节点neighbors,因为只是在内存中建立一个对象放入map中,后面当遍历到这个节点的时候,再去管他的neighbors,所以这是BFS,而不是DFS, 当时我就是这一点迷糊了,没理清思路。
当map中没有这样的关系(也就是说之前遍历其他点的相邻节点neighbors的时候没有访问过它)我们要新建一个节点,放在map中,value就是现在原图的节点的邻居的label。这样就是把newNode和它的neighbors连起来(newNode.list.add(..))同时和原图node的neighbors的关系建立起来,放到map中方便以后使用。
还有,如何能保证克隆的图里,没有重复元素呢 ?那就是只有在map中不存在这个点的时候,才把他们压入栈中,不然的话就会造成死循环。
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
if(node==null) return null;
UndirectedGraphNode newNode= new UndirectedGraphNode(node.label);
HashMap<UndirectedGraphNode, UndirectedGraphNode> map= new HashMap<UndirectedGraphNode,UndirectedGraphNode>();
Queue<UndirectedGraphNode> queue= new LinkedList<UndirectedGraphNode>();
queue.offer(node);
map.put(node, newNode);
while(!queue.isEmpty()){
UndirectedGraphNode temp= queue.poll();
newNode=map.get(temp); //map中肯定有这个temp,第一个点我们在循环前就加入了,后面的点当第一次访问的时候都会加入,第二次访问直接拿出来.
for(UndirectedGraphNode neighbor: temp.neighbors){
if(!map.containsKey(neighbor)){
map.put(neighbor, new UndirectedGraphNode(neighbor.label));
queue.offer(neighbor);
}
newNode.neighbors.add(map.get(neighbor));
}
}
return map.get(node);
}