三种做法。

方法一:先存后连

第一遍先从头到尾都把next连好,并且把原链表节点和新链表节点一一对应存进HashMap中。再对照HashMap一一连好Random。
(显然也可以首先存好节点对,最后一起连next和Random。)

import java.util.*;
public class Solution {
    public RandomListNode Clone(RandomListNode pHead){
        if(pHead==null) return null;
        RandomListNode root=new RandomListNode(pHead.label);
        RandomListNode curr=root;
        Map<RandomListNode, RandomListNode> map=new HashMap<>();
        map.put(pHead,curr);
        while(pHead.next!=null){
            RandomListNode next=new RandomListNode(pHead.next.label);
            curr.next=next;
            curr=next;
            pHead=pHead.next;
            map.put(pHead,curr);
        }
        for(RandomListNode i:map.keySet()){
            RandomListNode r=map.get(i);
            r.random=map.get(i.random);
        }
        return root;
    }
}

方法二:边连边存

连之前先检查对应的next,random节点是不是已经被新建出来了,能连好的next,random就连好,没有就新建再存。

import java.util.*;
public class Solution {
    public RandomListNode Clone(RandomListNode pHead){
        if(pHead==null) return null;
        RandomListNode root=new RandomListNode(pHead.label);
        RandomListNode curr=root;
        Map<RandomListNode, RandomListNode> map=new HashMap<>();
        map.put(pHead,curr);
        while(pHead.next!=null){
            RandomListNode next=curr;
            if(!map.containsKey(pHead.next))
                next=new RandomListNode(pHead.next.label);
            else
                next=map.get(pHead.next);
            curr.next=next;
            if(!map.containsKey(pHead.random)){
                RandomListNode r=pHead.random==null? null:
                    new RandomListNode(pHead.random.label);
                curr.random=r;
                map.put(pHead.random, r);
            }
            else
                curr.random=map.get(pHead.random);
            curr=curr.next;
            pHead=pHead.next;
        }
        curr.random=map.get(pHead.random);
        return root;
    }
}

方法三:“套娃做法”

就是前排里面的做法了。这个想法可以由HashMap推广得到。
为什么我们要建立HashMap呢?因为我们想要建立起原链表节点和新链表节点的一一对应。
那么直接在原链表节点后插入新链表节点不就好了嘛!
记得之后要“解套”,再变回两个单独的链表!

public class Solution {
    public RandomListNode Clone(RandomListNode pHead){
        if(pHead==null) return null;
        RandomListNode head=pHead;
        while(pHead!=null){
            RandomListNode curr=new RandomListNode(pHead.label);
            curr.next=pHead.next;
            pHead.next=curr;
            pHead=pHead.next.next;
        }
        pHead=head;
        while(pHead!=null){
            pHead.next.random=pHead.random==null? null:pHead.random.next;
            pHead=pHead.next.next;
        }
        pHead=head;
        RandomListNode qHead=head.next;
        RandomListNode ans=head.next;
        while(pHead!=null){
            if(qHead!=null) {pHead.next=qHead.next; pHead=pHead.next;}
            if(pHead!=null) {qHead.next=pHead.next; qHead=qHead.next;}          
        }
        return ans;
    }
}

方法二和方法三中需要尤其注意,random可以为null,所以选择条件不能丢!