描述
输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
解题思路
重点难点:复制出来的链表的随机指针如何完成复制, 复制时有的结点可能还未生成。因此我们需要先将这些节点复制出来,然后再完成随机指针映射,此时的关键是怎么才可以最快找到随机指针指向的结点。在此记录一种解法:
- 复制链表中所有结点并将新的结点插入原结点下一位置
- 初始化随机指针指向
- 从链表中拆出复制出来的结点生成新的链表
/*
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)
{
copy(pHead);
init(pHead);
return split(pHead);
}
/**
* 复制链表中所有结点,同时将新生成的结点插入到原结点的下一个位置
*/
public void copy(RandomListNode pHead){
RandomListNode current=pHead;
RandomListNode temp=null;
while(current!=null){
temp=new RandomListNode(current.label);
// 插入一个结点
temp.next=current.next;;
current.next=temp;
current=temp.next;
}
}
/**
* 处理链表中复制出的结点的随机指针
*/
public void init(RandomListNode pHead){
RandomListNode current=pHead;
RandomListNode next=null;
while(current!=null){
next=current.next;
RandomListNode random=current.random;
if(random!=null){
next.random=random.next;
}
current=next.next;
}
}
/**
*将复制出来的链表拆分成两个链表: 旧的链表删除复制结点;新的链表则由复制出来的结点构成
*/
public RandomListNode split(RandomListNode pHead){
RandomListNode newHead=new RandomListNode(0);
RandomListNode temp=newHead;
RandomListNode currentNode=pHead;
RandomListNode nextNode=null;
while(currentNode!=null){
nextNode=currentNode.next;
// 移除next结点-开始
temp.next=nextNode;
// 重复结点脱离原链
currentNode.next=nextNode.next;
nextNode.next=null;
// 移除next结点-结束
// 新链指针移动
temp=nextNode;
// 移动当前结点
currentNode=currentNode.next;
}
return newHead.next;
}
}