给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。要求返回这个链表的深度拷贝。
由题可知,此链表除过结点本身的值和next指向,每个结点还附加一个可以指向任何结点或空的random指向。我们先来创建这个类。
class CNode{
int val;
CNode next = null;
CNode random = null;
CNode(int val){
this.val = val;
}
}
那么上图的链表可以这样表示:
CNode h1 = new CNode(1);
CNode h2 = new CNode(3);
CNode h3 = new CNode(5);
CNode h4 = new CNode(7);
h1.next = h2;
h2.next = h3;
h3.next = h4;
h1.random = h3;
h2.random = h1;
h3.random = h3;
h4.random = null;
做好前面的准备,我们要想一想怎么复制这个链表,结点的值和其next指向是比较好复制的,那随机指向random要怎么复制呢 。
1.遍历链表,将值和指向拷贝至链表p2
CNode p1 = head;
while(p1!= null){
CNode p2 = new CNode(p1.val);
p2.next = p1.next;
p1.next = p2;
p1 = p2.next;
}
2.糅合链表p1和链表p2
让链表p1的结点依次指向链表p2所对应的结点。
(将所有的next指向改为红色箭头所指的指向)
p1 = head;
while(p1 != null){
CNode p2 = p1.next;
if(p1.random != null){
p2.random = p1.random.next;
}
p1 = p2.next;
}
糅合之后的链表:
3.复制random指向
例:
那在复制random的时候,只需要将p2.random = p1.random.next;即:
p1 = head;
while(p1 != null){
CNode p2 = p1.next;
if(p1.random != null){
p2.random = p1.random.next;
}
p1 = p2.next;
}
3.将俩个表分开
CNode一个新的结果链表,让p1.next为结果链表的头,依次拆开
p1 = head;
CNode result = head.next;//找到复制的链表的head
while(p1 != null) {
CNode p2 = p1.next;
p1.next = p2.next;
if(p2.next != null){
p2.next = p2.next.next;
}
p1 = p1.next;
}
完整程序:
https://github.com/WangWenQian12/Java_Practice/tree/master/JavaSE/IDEA/LinkedList/ComplexCopy