思路:这个算法的难点就难在链表有一个指向随机节点的引用,你不能确定这个引用指向哪一个节点,但是我们可以用选择参照的方式,来解决问题。用原链表作为参照物,head为原链表的某一节点,这个节点的next本来是指向下一个节点的,但是 现在,我们可以把这个next指向复制链表相对于原链表的相应节点headClone,然后再把headClone的next指向head的next,依次类推,到这里已经可以看出规律了,这个融合了原链表和复制链表的新链表的有一个特征,前后两个节点为原节点和复制节点的关系,这样的话,原节点的的随机节点引用指向的节点的next节点就是复制节点的随机节点引用该指向的节点,之后再将两个链表拆开,得到的其中一个链表就是我们需要的复制链表,代码如下:
/*
public class RandomListNode {
int label;
RandomListNode next = null;
RandomListNode random = null;
RandomListNode(int label) {
this.label = label;
}
}
*/
public class Solution {
public RandomListNode Clone(RandomListNode pHead){
if(pHead==null){
return null;
}
RandomListNode tempNode;
RandomListNode pHeadClone;
RandomListNode newHeadClone;
RandomListNode newHead = new RandomListNode(pHead.label); //新链表的头结点
for(pHeadClone=pHead, newHeadClone=newHead;pHeadClone!=null;){
tempNode = pHeadClone.next;
pHeadClone.next = newHeadClone;
newHeadClone.next = tempNode;
//进入下一次循环前的准备
pHeadClone = tempNode; //将当前节点移到下一个节点
if(pHeadClone!=null){
newHeadClone = new RandomListNode(pHeadClone.label); //复制当前节点
}
}
//复制random引用
for(pHeadClone=pHead, newHeadClone=newHead;pHeadClone!=null;){
tempNode = newHeadClone.next;
if(pHeadClone.random!=null){
newHeadClone.random = pHeadClone.random.next;
}else{
newHeadClone.random = null;
}
pHeadClone = tempNode;
if(pHeadClone!=null){
newHeadClone = pHeadClone.next;
}
}
//拆分两个链表
for(pHeadClone=pHead, newHeadClone=newHead;pHeadClone!=null;){
pHeadClone.next = newHeadClone.next; //恢复原链表
if(pHeadClone.next!=null){
newHeadClone.next = pHeadClone.next.next;
}else {
newHeadClone.next = null;
}
//准备下一次循环,引用变更
pHeadClone = pHeadClone.next;
newHeadClone = newHeadClone.next;
}
return newHead;
}
}