题目:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)
方法一:复制原始链表上的节点,然后用next指针串起来,然后设置每个节点的random指针。设置random指针的时候,需要从链表头结点开始经过o(n)步才能找到,这个时间复杂度是o(n^2)
方法二:使用HashMap,将链表的节点放入HashMap中,然后在复制链表的时候,去HashMap中拿指向的节点。这个就是用o(n)的空间来换取o(n)的时间复杂度
import java.util.HashMap;
/*
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 pHead;
}
//使用HashMap存放
RandomListNode target=new RandomListNode(pHead.label);
RandomListNode cur=pHead;
RandomListNode p=target;
HashMap<RandomListNode,RandomListNode> map=new HashMap<RandomListNode,RandomListNode>();
while(pHead!=null){
map.put(pHead,new RandomListNode(pHead.label));
pHead=pHead.next;
}
while(cur!=null){
p.next=map.get(cur.next);
p.random=map.get(cur.random);
cur=cur.next;
p=p.next;
}
return target;
}
}
方法三:将复制的节点放在原始链表后面。然后设置复制出来的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)
{
if(pHead==null){
return pHead;
}
RandomListNode cur=pHead;
//复制链表节点插到原链表节点后面
while(cur!=null){
RandomListNode clone=new RandomListNode(cur.label);
clone.next=cur.next;
cur.next=clone;
cur=clone.next;
}
cur=pHead;
//复制随意节点
while(cur!=null){
if(cur.random!=null){
cur.next.random=cur.random.next;
}
cur=cur.next.next;
}
//分割链表
cur=pHead;
RandomListNode pClone=pHead.next;
while(cur!=null){
RandomListNode cloneNode=cur.next;
cur.next=cloneNode.next;
cloneNode.next=cloneNode.next==null?null:cloneNode.next.next;
cur=cur.next;
}
return pClone;
}
}