给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的深拷贝。
示例:
输入:
{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}
解释:
节点 1 的值是 1,它的下一个指针和随机指针都指向节点 2 。
节点 2 的值是 2,它的下一个指针指向 null,随机指针指向它自己。
提示:
你必须返回给定头的拷贝作为对克隆列表的引用。
方法一:回朔。 如果没有随机指针,呢就是一条链进行深拷贝即可,但是因为随机指针的存在,链表就成为了一个有向图,因此我们需要按照图的遍历方式进行深拷贝,因为随机指针的随机性,使得这个图可能存在环,因此我们需要标记我们已经遍历过的节点,以防形成死循环。
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;
}
};
class Solution {
HashMap<Node,Node> visitedNode=new HashMap<>();
public Node copyRandomList(Node head) {
if(head==null)
return null;
if(visitedNode.containsKey(head))
return visitedNode.get(head);
Node node=new Node(head.val,null,null);
visitedNode.put(head, node);
node.next=copyRandomList(head.next);
node.random=copyRandomList(head.random);
return node;
}
}
方法二:迭代(O(n)的空间复杂度)
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;
}
};
class Solution {
HashMap<Node,Node> visitedNode=new HashMap<>();
public Node copyRandomList(Node head) {
if(head==null)
return null;
Node oldnode=head;
Node newnode=new Node(oldnode.val,null,null);
visitedNode.put(oldnode, newnode);
while(oldnode!=null)
{
newnode.random=getCloneNode(oldnode.random);
newnode.next=getCloneNode(oldnode.next);
oldnode=oldnode.next;
newnode=newnode.next;
}
return visitedNode.get(head);
}
private Node getCloneNode(Node node)
{
if(node==null)
return null;
if(visitedNode.containsKey(node))
return visitedNode.get(node);
else
{
visitedNode.put(node, new Node(node.val,null,null));
return visitedNode.get(node);
}
}
}
方法三:迭代(O(1)的空间复杂度)
方法参考题解:138题解的方法三
class Solution {
HashMap<Node,Node> visitedNode=new HashMap<>();
public Node copyRandomList(Node head) {
if(head==null)
return null;
Node ptr=head;
while(ptr!=null)
{
Node newnode=new Node(ptr.val,null,null);
newnode.next=ptr.next;
ptr.next=newnode;
ptr=newnode.next;
}
ptr=head;
while(ptr!=null)
{
ptr.next.random=(ptr.random!=null)?ptr.random.next:null;
ptr=ptr.next.next;
}
Node ptr_old_list=head;
Node ptr_new_list=head.next;
Node head_old=head.next;
while(ptr_old_list!=null)
{
ptr_old_list.next=ptr_old_list.next.next;
ptr_new_list.next=ptr_new_list.next!=null?ptr_new_list.next.next:null;
ptr_old_list=ptr_old_list.next;
ptr_new_list=ptr_new_list.next;
}
return head_old;
}
}