给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。
图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。
class Node {
public int val;
public List neighbors;
}
测试用例格式:
简单起见,每个节点的值都和它的索引相同。例如,第一个节点值为 1(val = 1),第二个节点值为 2(val = 2),以此类推。该图在测试用例中使用邻接列表表示。
邻接列表 是用于表示有限图的无序列表的集合。每个列表都描述了图中节点的邻居集。
给定节点将始终是图中的第一个节点(值为 1)。你必须将 给定节点的拷贝 作为对克隆图的引用返回。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/clone-graph
代码思路:
这道题的主要目的是遍历一遍图,然后把图的每一个节点copy一份,主要的难点在于如何找到自己已经创建过得节点,如何管理题目给出的node节点,和自己的node节点的对应关系,保证对相对应的节点做相同的操作。最难的点在于debug,由于leetcode的返回并不会告诉你哪一个节点出现问题了,也没有个过程,同时调试的时候node节点是node的指针值,也难以辨认。
代码如下:
public Node cloneGraph(Node node) {
Queue<Node> que=new LinkedList<Node>();
Queue<Node> quecopy=new LinkedList<Node>();
HashSet<Integer> set=new HashSet<Integer>();
HashMap<Integer,Node> setcopy=new HashMap<Integer,Node>();
que.add(node);
Node result=new Node(1,new ArrayList());
setcopy.put(1, result);
Node resultcurr=result;
Node temp;
Node curr;
quecopy.add(result);
while(!que.isEmpty()) {
curr=que.remove();
resultcurr=quecopy.remove();
if(!set.contains(curr.val)) {
set.add(curr.val);
resultcurr.val=curr.val;
//System.out.println("copy第"+curr.val+"个节点");
for(Node one :curr.neighbors) {
if(!setcopy.containsKey(one.val)) {
//System.out.println("邻居节点有:新建"+one.val+" ");
que.add(one);
temp=new Node(one.val,new ArrayList());
setcopy.put(temp.val, temp);
quecopy.add(temp);
resultcurr.neighbors.add(temp);
}else {
//System.out.println("邻居节点有:"+one.val+" ");
temp=setcopy.get(one.val);
resultcurr.neighbors.add(temp);
}
}
System.out.println();
}
}
return result;
}
代码分析:
时间复杂度和官方的解答是一致的,但是空间的复杂度,我这个方法会高出很多,因为,我不但多使用了一个quecopy去存储自己创建的节点队列,和que队列一同增减保证对相对应的节点做相同的操作。还多使用了一个setcopy用来找到自己创建的节点。
官方的代码总体思路是很简单的,但是官方代码将自己创建的节点放到了hashmap中,一方面可以方便的知道哪些节点是访问过得,也能找到创建过得节点,最后从hashmap中返回结果,也是非常巧妙了。
博主代码结果如下: