一.题目
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。要求返回这个链表的深拷贝。
二.输入输出示例
输入:
{"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}
解释:
节点 1 的值是 1,它的下一个指针和随机指针都指向节点 2 。
节点 2 的值是 2,它的下一个指针指向 null,随机指针指向它自己。
三.解题方法
1.先忽略链表的random,生成与原链表val相同的结点,进行以下方式的插入;
原链表:1 -> 2 -> 3 -> 4 -> 5
插入后的链表:1 -> 1 -> 2 -> 2 -> 3 -> 3 -> 4 -> 4 ->5 -> 5 (其中加粗的为新节点,random为null)
2.通过观察可以发现新结点的random为原结点random的后继结点(next);
例如: 1.random = 3 那么 1.random = 1.random.next 即为3(注意区分加粗与不加粗)
通过此方法遍历‘插入后的链表’,即可将random拷贝至新结点;
3.将原链表与新节点形成的链表分离开来;
插入后的链表:1 -> 1 -> 2 -> 2 -> 3 -> 3 -> 4 -> 4 ->5 -> 5
原链表:1 -> 2 -> 3 -> 4 -> 5
Copy链表:1 -> 2 -> 3 -> 4 -> 5
注意:在拆分时应给新链表赋一个head,否则将无法找到新链表的头结点
四.代码(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;
}
};
*/
class Solution {
public Node copyRandomList(Node head) {
if(head == null){ //如果时空链表则返回空
return null;
}
Node cur = head;
while(cur != null){ //形成新的链表
Node new_Node = new Node(cur.val);
new_Node.random = null;
new_Node.next = cur.next;
cur.next = new_Node;
cur = new_Node.next;
}
Node p1 = head;
while(p1!=null){ //给新结点复制random
Node p2 = p1.next;
if(p1.random !=null){
p2.random = p1.random.next;
}
p1 = p1.next.next;
}
Node new_list = head.next;
p1 = head;
while(p1!=null){ //将新链表与原链表拆分
Node p2 = p1.next;
p1.next = p2.next;
p1 = p2.next;
if(p2.next!=null){
p2.next = p2.next.next;
p2 = p1.next;
}
}
return new_list;
}
}