方法1:使用hash表对原链表节点进行克隆。该方法旨在建立原链表中每一个节点和其克隆节点的对应关系。但是该方法的额外空间复杂度为O(N)
方法2:使用有限节点。假设原始链表为1->2->3->null(rand指针没有标明),该方法分为三个步骤:
① 将原链表的每一个节点进行复制并将其插入在被复制的节点和该节点的下一个节点中间。该步操作后链表变为1->1'->2->2'->3->3'
② 开始连接rand指针。与①中操作类似
③ 将原始链表和克隆节点形成的链表进行分离
代码实现:
publicclassCopyListWithRandom{publicstaticclassNode{publicint value;publicNode next;publicNode rand;// 可能指向链表的任意一个节点,也可能指向nullpublicNode(int value){this.value = value;}}// 方法1:使用hash表对原链表节点进行克隆publicstaticNodecopyListWithRand1(Node head){// 建立原链表上每一个节点和新节点的对应关系HashMap<Node,Node> map =newHashMap<>();Node cur = head;while(cur !=null){
map.put(cur,newNode(cur.value));
cur = cur.next;}
cur = head;while(cur !=null){// cur指向的是原链表上的节点// map.get(cur)指向的是原链表上的节点对应的新节点// 将next指针和rand指针都一一对应即可
map.get(cur).next = map.get(cur.next);
map.get(cur).rand = map.get(cur.rand);
cur = cur.next;}return map.get(head);}// 方法2:使用有限节点publicstaticNodecopyListWithRand2(Node head){if(head ==null){returnnull;}Node cur = head;Node next =null;// 1.将原链表的每一个节点进行复制并将其插入在被复制的节点和该节点的下一个节点中间while(cur !=null){
next = cur.next;// 储存当前节点原来的下一个节点
cur.next =newNode(cur.value);// 当前节点的next指针指向克隆节点(克隆当前节点)
cur.next.next = next;// 克隆节点的next指向被克隆节点原来的下一个节点
cur = next;// 被克隆节点原来的下一个节点成为下一轮操作节点}
cur = head;Node curCopy =null;// 2.链表经过上述操作变为1->1'->2->2',此时开始连接rand指针while(cur !=null){
next = cur.next.next;
curCopy = cur.next;// 此时cur.rand.next已经确定为cur.rand的克隆节点,所以curCopy的rand指针可以直接指向该节点
curCopy.rand = cur.rand !=null? cur.rand.next :null;
cur = next;}Node res = head.next;
cur = head;// 3.将原始链表和克隆节点形成的链表进行分离while(cur !=null){
next = cur.next.next;
curCopy = cur.next;
cur.next = next;// 此时next.next已经确定为next的克隆节点,所以curCopy的next指针可以直接指向该节点
curCopy.next = next !=null? next.next :null;
cur = next;}return res;}}