在上图中,对于一个节点,它的 next 指针指向链表中的下一个节点。 next 指针是通常有向链表中有的部分且将所有节点 链接 起来。图中有趣的一点,也是这题有趣的一点在于 random 指针,正如名字所示,它可以指向链表中的任一节点也可以为空。
算法
1、从 头 指针开始遍历整个图。
我们将链表看做一张图。下图对应的是上面的有向链表的例子,Head 是图的出发节点。
2、当我们遍历到某个点时,如果我们已经有了当前节点的一个拷贝,我们不需要重复进行拷贝。
3、如果我们还没拷贝过当前节点,我们创造一个新的节点,并把该节点放到已访问字典中,即:
visited_dictionary[current_node] = cloned_node_for_current_node.
4、我们针对两种情况进行回溯调用:一个顺着 random 指针调用,另一个沿着 next 指针调用。步骤 1 中将 random 和 next 指针分别红红色和蓝色标注。然后我们分别对两个指针进行函数递归调用:
cloned_node_for_current_node.next = copyRandomList(current_node.next);
cloned_node_for_current_node.random = copyRandomList(current_node.random);
Java代码
/*
// Definition for a Node.
class Node {
public int val;
public Node next;
public Node random;
public Node() {}
public Node(int _val,Node _next,Node _random) {
val = _val;
next = _next;
random = _random;
}
};
*/
public Node copyRandomList(Node head) {
HashMap<Node, Node> visitedHash = new HashMap<Node, Node>();
if (head == null) {
return null;
}
if (this.visitedHash.containsKey(head)) {
return this.visitedHash.get(head);
}
Node node = new Node(head.val, null, null);
this.visitedHash.put(head, node);
node.next = this.copyRandomList(head.next);
node.random = this.copyRandomList(head.random);
return node;
}