給定一個鏈表,每個節點包含一個額外增加的隨機指針,該指針可以指向鏈表中的任何節點或空節點。
要求返回這個鏈表的深拷貝。
示例:
輸入:
{"$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;
}
}